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

如何在KeycloakWebSecurityConfigurerAdapter中校验用户分组

答案

KeycloakWebSecurityConfigurerAdapter 默认不直接支持用户组校验,你当前只能做角色校验的原因是:默认配置使用的SimpleAuthorityMapper只会解析Keycloak令牌中的角色字段,映射为Spring Security的权限标识,不会处理用户组字段。但你完全可以通过少量扩展配置实现用户组归属校验,不需要替换现有权限框架。

具体实现步骤

1. 配置Keycloak客户端将用户组信息注入令牌

首先在Keycloak管理后台完成配置,让登录返回的访问令牌携带用户所属组信息:

  • 进入你应用对应的客户端配置页,打开Mappers标签页
  • 新增一个类型为Group Membership的映射器
  • 自定义映射器名称,将Token Claim Name设置为groups,同时勾选「Add to access token」选项,保存配置即可。后续用户登录签发的JWT令牌中就会包含当前用户的所有所属组列表。

2. 自定义权限映射器,同时加载角色和用户组权限

替换你当前使用的SimpleAuthorityMapper,自定义一个权限映射器,同时解析令牌中的角色和用户组,统一转为Spring Security可识别的GrantedAuthority。为了方便区分角色和组,可以给组对应的权限加GROUP_前缀,和角色的ROLE_前缀做区分:

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
import org.springframework.security.core.context.SecurityContextHolder;
import org.keycloak.KeycloakPrincipal;
import org.keycloak.KeycloakSecurityContext;
import org.keycloak.representations.AccessToken;
import java.util.*;

public class KeycloakGroupAuthorityMapper implements GrantedAuthoritiesMapper {
    private static final String ROLE_PREFIX = "ROLE_";
    private static final String GROUP_PREFIX = "GROUP_";

    @Override
    public Collection<? extends GrantedAuthority> mapAuthorities(Collection<? extends GrantedAuthority> authorities) {
        Set<GrantedAuthority> result = new HashSet<>();
        // 保留原有角色映射逻辑
        authorities.forEach(auth -> {
            if (auth instanceof org.keycloak.adapters.springsecurity.KeycloakRole) {
                result.add(new SimpleGrantedAuthority(ROLE_PREFIX + auth.getAuthority()));
            }
        });
        // 从令牌中提取用户组信息,映射为权限
        KeycloakPrincipal<KeycloakSecurityContext> principal = (KeycloakPrincipal<KeycloakSecurityContext>) SecurityContextHolder
                .getContext().getAuthentication().getPrincipal();
        AccessToken token = principal.getKeycloakSecurityContext().getToken();
        Object groupsClaim = token.getOtherClaims().get("groups");
        if (groupsClaim instanceof List<?> groups) {
            groups.forEach(group -> {
                String groupName = ((String) group).replaceFirst("^/", "");
                result.add(new SimpleGrantedAuthority(GROUP_PREFIX + groupName));
            });
        }
        return result;
    }
}

修改你原有配置中的configureGlobal方法,将默认的权限映射器替换为自定义实现:

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
    // 替换为支持组映射的权限转换器
    keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new KeycloakGroupAuthorityMapper());
    auth.authenticationProvider(keycloakAuthenticationProvider);
}

3. 在接口权限规则中配置组校验

完成映射后,就可以直接使用Spring Security原生的hasAuthority方法配置接口的组访问权限,示例配置如下:

@Override
protected void configure(HttpSecurity http) throws Exception {
    super.configure(http);
    http.authorizeRequests(a-> a
            .antMatchers("/customers*", "/users*").hasRole("user")
            // 限制仅属于"vip_user"组的用户可访问/vip开头的接口
            .antMatchers("/vip/**").hasAuthority("GROUP_vip_user")
            .anyRequest().permitAll());
}

如果你需要实现更复杂的组校验逻辑(比如同时匹配多个组、按组路径层级做权限匹配),也可以不做权限映射,直接在自定义校验方法中读取Keycloak令牌的groups字段做判断,灵活度更高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 11:18:15