我目前正在实现一个系统,将Sping Boot 作为资源服务器,将Keycloak作为授权服务器。我希望能够为用户创建不同的角色,但这应该会自动发生,因此没有管理员管理Keycloak后端。
我已经阅读了有关Keycloak管理API的内容,但我对这种方法非常不确定,因为这意味着将登录凭据存储在我的资源服务器中,这根本不是最佳实践,我想。所以我想储存(业务上下文)角色,但不为每个端点实现自己的授权方法。我希望能够将存储在资源服务器中的角色与Spring Security 一起使用,例如hasRole()方法,而且还包括OPEN ID身份验证(从授权中移交角色)已经使用的所有其他功能服务器上。
那么,我该怎么做呢?是否有一种安全的方法可以从资源服务器更新授权服务器中的用户角色?这对我来说似乎不太可能,因为(尽管在我的情况下不是这样)授权服务器可能不属于资源所有者。
或者,作为另一种方法,是否可以将从keycloak传递给 Boot 的角色与存储在资源服务器数据库中的角色融合在一起,并在通过keycloak对用户进行身份验证后查找它们?
我会非常高兴的一些代码片段,但指针的教程解释的主题是一样赞赏。
2条答案
按热度按时间vatpfxk51#
所以,在谷歌上搜索了几次之后,我找到了一个完美的解决方案。这里有文档:https://www.baeldung.com/spring-security-map-authorities-jwt,但实际上我不能做很多。
有一个关于stackoverflow Spring Security: mapping OAuth2 claims with roles to secure Resource Server endpoints的答案,运行得很好。但也有我的源代码。
您可以通过任何方式为经过身份验证的用户计算角色,例如使用JPA或存储用户数据的其他数据源。整个JWT令牌将交给您,正如您所看到的,我使用的是“子”密钥,但是对于不同的授权服务器实现,您应该自己选择唯一标识符。
毕竟,我选择了资源服务器持久角色管理。我认为这是一个很好的实践,因为业务上下文应该存储在那里。我希望我可以帮助每个有同样问题的人。
7jmck4yq2#
我不太同意你的看法:在我看来,授权服务器是管理身份验证和授权数据的最佳位置。
我更喜欢为授权服务器提供“插件”(Keycloak中所谓的Map器),以便使用我需要的私有声明来丰富访问令牌,并且在资源服务器上,仅从访问令牌声明构建Spring安全上下文。
这意味着:
最后,这也会导致定义一个自定义身份验证转换器,但每次生成访问令牌(由授权服务器将其添加到访问令牌中)时,DB访问(检索角色或其他内容)只发生一次,而不是每次请求(由资源服务器构建安全上下文)时发生一次。
编辑
我没有资源服务器调用授权服务器管理API的示例,但这只是一个问题:
WebClient
、RestTemplate
、@FeignClient
或任何您喜欢的客户端),该客户端能够使用客户端凭据来获取访问令牌我有一个例子,Keycloak联系一个资源服务器,添加一个私有声明,其中一些安全数据不是它本机处理的(用户之间的角色委派)。这是用this Keycloak "mapper"完成的。私有声明在资源服务器上由一个自定义的
JwtAuthenticationConverter
使用:在这个项目中,我没有使用JwtAuthenticationToken
作为Authentication
,而是使用一个自定义值:ProxiesAuthentication
(它包含负责解析私有声明的ProxiesClaimSet
)。本示例中的流程是授权服务器调用资源服务器,因为Keycloak不知道“用户代理”,也没有为它公开API。但结果是相同的:所有的安全数据都包含在令牌中,使得资源服务器不需要昂贵的操作(DB访问或web服务调用)来建立安全上下文。