所以我按照一个指南设置了Keycloak,以通过Spring Security保护我的Sping Boot REST API。以前,我的应用程序依赖于一个标准的用户详细信息服务来验证用户。我的代码依赖于能够访问当前登录用户的用户名。然而,现在我切换到Keycloak,我只接收到用户名“anonymousUser”。
如何正确配置此选项,使以下代码返回首选用户名:public static String getCurrentUsername() {
return (String) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
}
我尝试在Keycloak上修改客户端和用户的配置,但即使是举个例子,添加角色也没有效果,Sping Boot 只返回[ANONYMOUS_USER]的角色。
1条答案
按热度按时间s4n0splo1#
您不可能从
AnonymousAuthenticationToken
获取当前用户的任何信息:Authentication
的此实现在请求未成功授权(无法识别用户)时置于安全上下文中。这意味着:关于如何使用Keycloak配置Spring-boot 3资源服务器(和客户端)的基本信息,请参阅我对这个问题的回答:Use Keycloak Spring Adapter with Spring Boot 3
在resource-servers中成功进行OAuth2授权的Spring-security默认
Authentication
是JwtAuthenticationToken
,它返回Jwt
示例principal
。您可以从此Jwt
示例中获取任何访问令牌声明。下面是preferred_username
的示例。打开一个访问-https://jwt.io等工具中的一个令牌,用于查找具有您正在查找的用户名值的声明的名称(它也可以是sub
、email
或您在Keycloak中配置的任何私有声明)如果你希望
getPrincipal()
返回用户名而不是Jwt
示例,你必须提供你自己的Authentication
实现,你可以使用JwtAuthenticationToken
作为基础(但这不是最佳选择,请参阅下面的注解):只需根据我上面链接的答案调整
Jwt2AuthenticationConverter
即可重要提示
您最好使用
authentication.getName()
而不是authentication.getPrincipal()
来访问用户名。principal
在Authentication
中被键入为Object
,这使得您的表达式非常脆弱:您可以获得任何类型的数据作为主体(取决于安全上下文中的身份验证类型),并且在某些情况下您实际上无法控制它(例如,由于未授权请求,您当前拥有的AnonymousAuthenticationToken
示例)。但是,
JwtAuthenticationToken::getName
返回subject(sub
claim),因此您仍然需要提供自己的Authentication
实现,以便成功授权在getName()
的新@Override中返回preferred_username
。MyAuthentication
将为:如果请求授权成功,使用相同的
Jwt2AuthenticationConverter
bean从默认JwtAuthenticationToken
切换到MyAuthentication
。