Keycloak组授权策略未生效,用户仍可跨应用登录求助
问题分析与解决方案
你的问题核心在于Keycloak的客户端授权策略仅在Keycloak端配置是不够的,应用端必须主动校验用户的权限/组信息,同时需要确保Keycloak的配置完整,Token能携带必要的组数据。以下是具体解决步骤:
一、检查Keycloak端的授权配置是否完整
- 确认客户端授权开关与权限关联
- 进入「客户端 > client1/client2 > 授权」,确保「授权」处于启用状态。
- 进入「权限」页面,检查你创建的资源权限:
- 资源需覆盖对应应用的所有访问路径(比如为app1创建资源
app1-resource,设置URI为/*); - 权限需关联对应的组策略(比如client1的权限关联group1的组策略,逻辑为「允许该组访问」);
- 确保权限和策略均处于「启用」状态。
- 资源需覆盖对应应用的所有访问路径(比如为app1创建资源
- 组策略配置校验
- 进入「策略」页面,查看对应组策略:确认已选中目标群组,策略逻辑为「用户必须属于该组」,且状态为启用。
- 确保Token携带组信息
- 进入「客户端 > client1/client2 > 客户端范围」,添加内置的
groups客户端范围; - 若未添加,可在「Mappers」页面新建「组映射器」:
- 类型选择「Group Membership」;
- 设置「Token Claim Name」为
groups,勾选「Add to ID token」和「Add to access token」; - 确保「Full Scope Allowed」在客户端设置中处于开启状态,或手动添加
groups到「Scope」列表。
- 进入「客户端 > client1/client2 > 客户端范围」,添加内置的
二、应用端实现权限校验(分Spring Boot版本)
Spring Boot 2.7(app2)
使用Spring Security OAuth2资源服务器组件,直接校验Token中的组信息:
- 依赖配置(pom.xml):
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-resource-server</artifactId> </dependency> - 配置文件(application.properties):
spring.security.oauth2.resourceserver.jwt.issuer-uri=http://你的Keycloak地址/auth/realms/你的Realm名 spring.security.oauth2.resourceserver.jwt.jwk-set-uri=${spring.security.oauth2.resourceserver.jwt.issuer-uri}/protocol/openid-connect/certs - Security配置类:
@Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth // 仅允许group2组的用户访问app2 .anyRequest().hasAuthority("GROUP_group2") ) .oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults())); return http.build(); } }注:Keycloak默认会给组权限添加
GROUP_前缀,若自定义了前缀需对应调整。
Spring Boot 1.5(app1)
使用Keycloak官方Spring Boot Starter实现校验:
- 依赖配置(pom.xml):
<dependency> <groupId>org.keycloak</groupId> <artifactId>keycloak-spring-boot-starter</artifactId> <version>21.1.1</version> </dependency> - 配置文件(application.properties):
keycloak.auth-server-url=http://你的Keycloak地址/auth keycloak.realm=你的Realm名 keycloak.resource=client1 keycloak.use-resource-role-mappings=true keycloak.bearer-only=true # 配置访问控制,仅允许group1组访问 keycloak.security-constraints[0].auth-roles[0] = group1 keycloak.security-constraints[0].security-collections[0].patterns[0] = /* - 若需自定义Security逻辑,可继承
KeycloakWebSecurityConfigurerAdapter:@Configuration @EnableWebSecurity public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter { @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { KeycloakAuthenticationProvider provider = keycloakAuthenticationProvider(); provider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper()); auth.authenticationProvider(provider); } @Bean @Override protected SessionAuthenticationStrategy sessionAuthenticationStrategy() { return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl()); } @Override protected void configure(HttpSecurity http) throws Exception { super.configure(http); http.authorizeRequests() .anyRequest().hasRole("group1"); } }
三、调试与验证
- 登录应用后,在代码中打印
Authentication对象的权限信息,确认是否包含对应组的权限标识; - 解析登录获取的Token,检查
groups字段是否包含目标群组名称; - 查看Keycloak服务器日志,确认授权请求无错误,策略已正确匹配。
内容的提问来源于stack exchange,提问作者Karthik Sankaran
相关产品推荐
相关产品推荐

