我正在开发一个使用密钥罩身份验证服务器的Spring后端.我正在努力让基于角色的授权发挥作用.我已经在我的领域中创建了一个用户"dev_admin",并为他分配了领域角色"admin".我有一个端点"Debuf/admin",只有具有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用户身份登录并try 访问admin端点之后,我返回错误403.这是来自弹簧控制台的信息:
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=dev@admin.com, 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=dev@admin.com, 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=dev@admin.com, 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
我还使用"imperassate"功能判断了dev_admin JWT内标识,该角色包含在该内标识中.我还注意到,在我的浏览器中,保存为Cookie的令牌要短得多,并且不包含该角色.这些都是我找到的线索,但我仍然不知道为什么它不起作用.如果有人知道发生了什么,那将是非常有帮助的.
编辑:顺便说一句,我没有使用 keys 斗篷适配器.它看起来就像这样,因为"keyloaklogouthandler"将请求发送到密钥伪装注销端点
我还应该提到,在我的例子中,客户端和资源服务器是同一服务器.我认为这个问题与安全配置有关.以下是我的申请表.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