我正在开发一个使用keycloak认证服务器的spring后端。我正在努力获得基于角色的授权。我在我的领域中创建了一个用户“dev_admin”,并将领域角色“admin”赋予了他。我有一个端点“debuf/admin”,它只对具有管理员角色的用户可访问。我的安全配置看起来像这样:
@Configuration
@EnableWebSecurity
public class SecurityConfig {
private final KeycloakLogoutHandler keycloakLogoutHandler;
SecurityConfig(KeycloakLogoutHandler keycloakLogoutHandler) {
this.keycloakLogoutHandler = keycloakLogoutHandler;
}
@Bean
public SecurityFilterChain clientFilterChain(HttpSecurity http) throws Exception {
return http
.authorizeHttpRequests(auth -> {
auth
.requestMatchers(new AntPathRequestMatcher("/debug/public")).permitAll()
.requestMatchers(new AntPathRequestMatcher("/debug/authenticated")).authenticated()
.requestMatchers(new AntPathRequestMatcher("/debug/admin")).hasAnyRole("admin")
.anyRequest().authenticated();
})
.oauth2Login(Customizer.withDefaults())
.logout((conf) -> {
conf.addLogoutHandler(keycloakLogoutHandler);
conf.logoutSuccessUrl("/index");
})
.build();
}
}
但是,在我以dev_admin用户身份登录并尝试访问admin端点后,我返回错误403。这是来自spring控制台的:
2023-09-10T19:44:54.653+02:00 TRACE 1400 --- [nio-8080-exec-7] estMatcherDelegatingAuthorizationManager : Authorizing SecurityContextHolderAwareRequestWrapper[ org.springframework.security.web.header.HeaderWriterFilter$HeaderWriterRequest@5f29c29e]
2023-09-10T19:44:54.653+02:00 TRACE 1400 --- [nio-8080-exec-7] estMatcherDelegatingAuthorizationManager : Checking authorization on SecurityContextHolderAwareRequestWrapper[ org.springframework.security.web.header.HeaderWriterFilter$HeaderWriterRequest@5f29c29e] using AuthorityAuthorizationManager[authorities=[ROLE_admin]]
2023-09-10T19:44:54.653+02:00 TRACE 1400 --- [nio-8080-exec-7] w.c.HttpSessionSecurityContextRepository : Retrieved SecurityContextImpl [Authentication=OAuth2AuthenticationToken [Principal=Name: [dev_admin], Granted Authorities: [[OIDC_USER, SCOPE_email, SCOPE_openid, SCOPE_profile]], User Attributes: [{at_hash=1blJDsXc37Pz3uyqygg43A, sub=413591c7-3213-40a4-be2d-82dc69fe1264, email_verified=true, iss=http://localhost:8081/realms/users, typ=ID, preferred_username=dev_admin, given_name=dev, nonce=f_D-DARLucc5Y0Uau8QLhgv2srTM0gK3MDA1zpaDXDM, sid=fab4e120-b249-4e76-bffb-c5a4820fa536, aud=[core-server], acr=1, azp=core-server, auth_time=2023-09-10T17:44:50Z, name=dev admin, exp=2023-09-10T17:49:50Z, session_state=fab4e120-b249-4e76-bffb-c5a4820fa536, family_name=admin, iat=2023-09-10T17:44:50Z, [email protected], jti=a7e9ff04-2526-4ff8-82c1-1216ee6d673a}], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=95CD2FEF619B032D2A30C89CFAD0740C], Granted Authorities=[OIDC_USER, SCOPE_email, SCOPE_openid, SCOPE_profile]]] from SPRING_SECURITY_CONTEXT
2023-09-10T19:44:54.653+02:00 TRACE 1400 --- [nio-8080-exec-7] o.s.s.w.a.AnonymousAuthenticationFilter : Did not set SecurityContextHolder since already authenticated OAuth2AuthenticationToken [Principal=Name: [dev_admin], Granted Authorities: [[OIDC_USER, SCOPE_email, SCOPE_openid, SCOPE_profile]], User Attributes: [{at_hash=1blJDsXc37Pz3uyqygg43A, sub=413591c7-3213-40a4-be2d-82dc69fe1264, email_verified=true, iss=http://localhost:8081/realms/users, typ=ID, preferred_username=dev_admin, given_name=dev, nonce=f_D-DARLucc5Y0Uau8QLhgv2srTM0gK3MDA1zpaDXDM, sid=fab4e120-b249-4e76-bffb-c5a4820fa536, aud=[core-server], acr=1, azp=core-server, auth_time=2023-09-10T17:44:50Z, name=dev admin, exp=2023-09-10T17:49:50Z, session_state=fab4e120-b249-4e76-bffb-c5a4820fa536, family_name=admin, iat=2023-09-10T17:44:50Z, [email protected], jti=a7e9ff04-2526-4ff8-82c1-1216ee6d673a}], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=95CD2FEF619B032D2A30C89CFAD0740C], Granted Authorities=[OIDC_USER, SCOPE_email, SCOPE_openid, SCOPE_profile]]
2023-09-10T19:44:54.653+02:00 TRACE 1400 --- [nio-8080-exec-7] o.s.s.w.a.ExceptionTranslationFilter : Sending OAuth2AuthenticationToken [Principal=Name: [dev_admin], Granted Authorities: [[OIDC_USER, SCOPE_email, SCOPE_openid, SCOPE_profile]], User Attributes: [{at_hash=1blJDsXc37Pz3uyqygg43A, sub=413591c7-3213-40a4-be2d-82dc69fe1264, email_verified=true, iss=http://localhost:8081/realms/users, typ=ID, preferred_username=dev_admin, given_name=dev, nonce=f_D-DARLucc5Y0Uau8QLhgv2srTM0gK3MDA1zpaDXDM, sid=fab4e120-b249-4e76-bffb-c5a4820fa536, aud=[core-server], acr=1, azp=core-server, auth_time=2023-09-10T17:44:50Z, name=dev admin, exp=2023-09-10T17:49:50Z, session_state=fab4e120-b249-4e76-bffb-c5a4820fa536, family_name=admin, iat=2023-09-10T17:44:50Z, [email protected], jti=a7e9ff04-2526-4ff8-82c1-1216ee6d673a}], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=95CD2FEF619B032D2A30C89CFAD0740C], Granted Authorities=[OIDC_USER, SCOPE_email, SCOPE_openid, SCOPE_profile]] to access denied handler since access is denied
我还使用“impersonate”特性检查了dev_adminJWT令牌,该角色包含在令牌中。我还注意到,在我的浏览器中,保存为cookie的令牌要短得多,并且不包含角色。这些都是我找到的线索,但我仍然不知道为什么它不工作。如果有人知道,这将是非常有帮助的。
编辑:顺便说一下,我没有使用keycloak适配器。它看起来是这样的,因为“keycloaklogouthandler”向keycloaks logout端点发送请求
我还应该提到,在我的例子中,客户端和资源服务器是同一个服务器。我认为问题与安全配置有关。下面是我的应用程序.yml:
security:
oauth2:
resourceserver.jwt:
issuer-uri: ${keycloak.baseUrl}/realms/${keycloak.userRealm}
jwk-set-uri: ${keycloak.baseUrl}/auth/realms/${keycloak.userRealm}/protocol/openid-connect/certs
client:
registration.keycloak:
client-id: myclient
authorization-grant-type: authorization_code
scope: openid
admin_user: ???
admin_password: ???
provider.keycloak:
issuer-uri: ${keycloak.baseUrl}/realms/${keycloak.userRealm}
user-name-attribute: preferred_username
2条答案
按热度按时间r7xajy2e1#
根据手册,您应该提供
GrantedAuthoritiesMapper
bean或重写OAuth2UserService
。不要将Keycloak适配器用于Spring。它很久以前就被弃用了,并且不适用于Spring Security 6 / Boot 3。
不从Keycloak中获取用户角色。这样效率太低了。相反,从标记中读取它。当你写一个OAuth2客户端(它读取ID令牌,而不是访问令牌)时,你可能需要激活Map器:
Client scopes
->roles
->Mappers
->realm roles
并启用Add to ID token
和Add to userinfo
(如果您使用客户端角色,您可以对它执行相同的操作)。另一个答案包含了从Keycloak角色到资源服务器和客户端中的Spring权限的示例转换。
zf9nrax12#
您在
SecurityConfig
中指定角色的方式似乎有问题。要对Keycloak使用基于角色的授权,您需要使用Keycloak特定的角色前缀来指定角色。默认情况下,Keycloak对角色使用ROLE_
前缀。以下是如何修改
SecurityConfig
以使用正确的角色前缀:在此修改后的配置中:
我们扩展了
KeycloakWebSecurityConfigurerAdapter
以利用Keycloak特有的特性。我们将
AuthenticationManagerBuilder
配置为使用Keycloak提供的keycloakAuthenticationProvider
。请确保您的Keycloak领域配置与此设置匹配,特别是关于角色名称。Keycloak中的角色应该命名为“admin”,而不带
ROLE_
前缀。希望我能帮上忙。
此外,确保Sping Boot 应用程序的Keycloak客户端配置包括正确的角色Map。
完成这些修改后,再次尝试访问
/debug/admin
端点。如果在Keycloak中正确分配了角色,并且您的Keycloak客户端配置是准确的,则基于角色的授权应按预期工作。