You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Keycloak集成Google登录后基于角色的访问控制失效问题

解决方案:Keycloak + Spring Boot Google登录角色权限配置

一、Keycloak端正确配置角色与JWT映射

1. 创建Realm角色

  • 进入google-teste Realm → Roles → Add role
  • 创建user和admin两个Realm角色并保存。

2. 设置默认角色(自动赋予所有新用户)

  • 在Realm的Roles → Default Roles
  • 将user角色添加到Default Roles列表,保存后所有通过Google登录的新用户会自动获得user角色。

3. 确保客户端包含角色Scope并正确映射

  • 进入客户端spring-security-keycloak → Client scopes
  • 确认roles默认Client Scope已添加到Assigned client scopes
  • 点击roles Scope → Mappers → 找到realm roles映射器:
    • 开启Enabled状态
    • 确认Token Claim Name为realm_access.roles
    • Claim JSON Type设为String,Multivalued设为On
    • Role prefix留空,保存设置。

4. 手动为用户分配Admin角色

  • 进入Realm的Users → 通过preferred_username找到Google登录的用户
  • 进入用户详情 → Role mappings
  • 在Available roles中选择admin,添加到Assigned roles并保存。

二、Spring Boot端调整权限配置

1. 自定义JWT权限转换器(处理角色前缀)

Spring Security的hasRole()会自动添加ROLE_前缀,需将Keycloak返回的纯角色名转换为对应格式:

import org.springframework.core.convert.converter.Converter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.jwt.Jwt;

import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

public class KeycloakJwtGrantedAuthoritiesConverter implements Converter<Jwt, Collection<GrantedAuthority>> {
    @Override
    public Collection<GrantedAuthority> convert(Jwt jwt) {
        List<String> roles = jwt.getClaimAsList("realm_access.roles");
        return roles == null ? List.of() : roles.stream()
                .map(role -> new SimpleGrantedAuthority("ROLE_" + role))
                .collect(Collectors.toList());
    }
}

2. 更新SecurityConfig配置

将自定义转换器加入OAuth2资源服务器的JWT配置:

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        return http
                .authorizeHttpRequests(authorizeConfig -> {
                    authorizeConfig.requestMatchers("/public", "/logout").permitAll();
                    authorizeConfig.requestMatchers("/admin").hasRole("admin");
                    authorizeConfig.requestMatchers("/usuario").hasRole("user");
                    authorizeConfig.anyRequest().authenticated();
                })
                .oauth2Login(Customizer.withDefaults())
                .oauth2ResourceServer(config -> {
                    config.jwt(jwtConfig -> {
                        jwtConfig.jwtAuthenticationConverter(jwtAuthenticationConverter());
                    });
                })
                .build();
    }

    @Bean
    JwtAuthenticationConverter jwtAuthenticationConverter() {
        JwtAuthenticationConverter converter = new JwtAuthenticationConverter();
        converter.setJwtGrantedAuthoritiesConverter(new KeycloakJwtGrantedAuthoritiesConverter());
        return converter;
    }
}

可选方案:使用hasAuthority替代hasRole

若不想自定义转换器,可直接修改权限判断逻辑,将hasRole("admin")改为hasAuthority("admin"),hasRole("user")改为hasAuthority("user"),直接匹配Keycloak返回的角色名称。

三、验证配置

  1. 重启Spring Boot与Keycloak服务
  2. Google登录后访问/cookie接口,检查Authorities是否包含对应权限
  3. 查看JWT内容,确认realm_access.roles中包含user(所有用户)和admin(已分配用户)
  4. 测试路由:普通用户可访问/usuario,无法访问/admin;admin用户可访问两个路由。

内容的提问来源于stack exchange,提问作者PauloRamos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 22:55:58