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

如何修改Spring Boot Keycloak Adapter从JWT根节点roles[]提取角色

自定义Spring Boot Keycloak Adapter角色提取逻辑

方案一:实现GrantedAuthoritiesMapper接口

这是最简洁的实现方式,通过自定义权限映射器覆盖默认角色提取逻辑。

  • 创建自定义映射器类,直接从JWT根节点roles[]提取角色:
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

public class CustomKeycloakRolesMapper implements GrantedAuthoritiesMapper {

    @Override
    public Collection<? extends GrantedAuthority> mapAuthorities(Collection<? extends GrantedAuthority> authorities) {
        // 获取JWT中的根节点roles字段
        KeycloakAuthenticationToken token = (KeycloakAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        List<String> roles = token.getAccount().getKeycloakSecurityContext().getToken().getOtherClaims().get("roles", List.class);
        
        // 转换为Spring Security标准权限对象,添加ROLE_前缀适配框架规范
        return roles.stream()
                .map(role -> new SimpleGrantedAuthority("ROLE_" + role))
                .collect(Collectors.toList());
    }
}
  • 在Spring Security配置类中注册该映射器:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter;

@Configuration
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {

    @Bean
    public GrantedAuthoritiesMapper customRolesMapper() {
        return new CustomKeycloakRolesMapper();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http.authorizeRequests()
                .anyRequest().authenticated();
    }

    // 补充其他必要配置(如AuthenticationManagerBuilder初始化等)
}

方案二:重写KeycloakAuthenticationProvider

如果需要更深度的自定义控制,可以直接替换默认的认证提供者,重写权限提取方法。

  • 创建自定义认证提供者类:
import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider;
import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

public class CustomKeycloakAuthenticationProvider extends KeycloakAuthenticationProvider {

    @Override
    protected Collection<? extends GrantedAuthority> extractAuthorities(KeycloakAuthenticationToken token) {
        // 直接从JWT根节点读取roles列表
        List<String> roles = token.getAccount().getKeycloakSecurityContext().getToken().getOtherClaims().get("roles", List.class);
        
        // 转换为Spring Security权限对象
        return roles.stream()
                .map(role -> new SimpleGrantedAuthority("ROLE_" + role))
                .collect(Collectors.toList());
    }
}
  • 在Security配置类中替换默认提供者:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter;

@Configuration
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(customKeycloakAuthenticationProvider());
    }

    @Bean
    public CustomKeycloakAuthenticationProvider customKeycloakAuthenticationProvider() {
        return new CustomKeycloakAuthenticationProvider();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http.authorizeRequests()
                .anyRequest().authenticated();
    }

    // 补充其他必要配置(如KeycloakAuthenticationEntryPoint等)
}

注意事项

  • 需确保JWT令牌根节点存在roles[]字段,建议添加空值判断避免空指针异常。
  • Spring Security默认要求角色以ROLE_前缀开头,添加前缀后可直接使用hasRole()表达式进行权限控制。
  • 自定义逻辑会完全覆盖默认的角色提取行为,无需修改keycloak.use-resource-roles-mapping配置项。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 14:35:23