我正在开发一个网站。
前端(SPA/vue.js)<->REST后端(Spring Boot 3.2.1,Java 21)
我选择 keycloak IDP 作为授权服务器,以免从头开始编写注册和授权的自定义实现。这是我第一次使用 keycloak。
我使用了spring-addons软件,并根据示例实现了BFF设计。
前端<->Spring Gateway(客户端ouath2)<->Spring REST后端(oauth2资源服务器)
我面临一个问题,我不明白如何将用户从 keycloak 绑定到我的 Hibernate 实体。
简单的例子:
@Entity(name = "post")
public class Post {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Access(AccessType.PROPERTY)
private Intteger id;
// another fields
@Column(name = "content")
private String content;
@Column(name = "author_id", insertable = false, updatable = false)
private Integer authorId; // how to ??? Keycloak user id is GUID...
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", referencedColumnName = "id")
private KeycloakUser author; // how to ??? KeycloakUser - example
// constructors / getters / setters omitted
}
问题是如何将他们的作者分配给我的实体,以便稍后使用 JPA 我可以根据请求提取它们,例如
findById
?
我找到了一个解决方案,事实上我需要维护一个单独的应用程序用户数据库,有两个实现选项:
一个过滤器,检查当前授权用户是否存在,如果他没有在应用程序数据库中注册,则注册他;
SPI,一个事件系统,可用于拦截新用户注册事件并将其添加到应用程序的用户数据库中。
到目前为止,这两种选择对我个人来说都令人怀疑,我想了解解决此类问题的最佳实践,如果可能的话,通过示例。
答案是“你可能不应该”。
您应该考虑在多服务架构中,其中 OAuth2 授权服务器(在您的例子中为 Keycloak)是负责用户数据的服务。其他服务仅在 Keycloak 中为用户存储一个不可变标识符(
sub
声明是自然的候选者,但您也可以使用preferred_username
,如果它不能随时间变化)。
需要超过此 ID 的服务只会在访问当前用户数据时读取访问令牌声明,或使用 Keycloak 的“admin”API 获取任何其他用户的当前值。
如果复制用户数据,您将不可避免地遇到同步问题和不一致。
你可以浏览这个项目我就是这样做的