如何修改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
相关产品推荐
相关产品推荐

