Spring OAuth2资源服务器:roles声明无法转为权限问题求助
问题描述
从Spring Authorization Server获取的Access Token包含roles声明,已通过配置JwtAuthenticationConverter尝试将roles转换为authorities,配置代码如下:
@Bean public SecurityFilterChain securityFilterChain(HttpSecurity http, JwtAuthenticationConverter jwtAuthenticationConverter) throws Exception { http .authorizeHttpRequests(authorize -> authorize .anyRequest().authenticated() ) .cors(Customizer.withDefaults()) .oauth2Login(Customizer.withDefaults()) .oauth2Client(Customizer.withDefaults()) .oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt->jwt.jwtAuthenticationConverter(jwtAuthenticationConverter))); return http.build(); }
@Bean public JwtAuthenticationConverter jwtAuthenticationConverter(){ JwtGrantedAuthoritiesConverter grantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter(); grantedAuthoritiesConverter.setAuthoritiesClaimName("roles"); JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter(); jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(grantedAuthoritiesConverter); return jwtAuthenticationConverter; }
但使用@PreAuthorize("hasAuthority('USER')")进行权限验证时返回“Access denied”,仅SCOPE相关权限(如@PreAuthorize("hasAuthority('SCOPE_SOMETHING')"))可正常生效,需将roles中的权限正确加入authorities。
问题原因
JwtGrantedAuthoritiesConverter默认会为转换后的权限添加**SCOPE_**前缀,即便指定了自定义的权限声明字段(如roles)。若token中roles字段的值为["USER"],转换器会自动将其转为SCOPE_USER,而非预期的USER,导致hasAuthority('USER')无法匹配对应权限。
解决方案
修改JwtGrantedAuthoritiesConverter的配置,将权限前缀设置为空字符串,保留roles声明里的原始权限值:
@Bean public JwtAuthenticationConverter jwtAuthenticationConverter(){ JwtGrantedAuthoritiesConverter grantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter(); grantedAuthoritiesConverter.setAuthoritiesClaimName("roles"); // 关键配置:移除默认的SCOPE_前缀 grantedAuthoritiesConverter.setAuthorityPrefix(""); JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter(); jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(grantedAuthoritiesConverter); return jwtAuthenticationConverter; }
若需同时保留SCOPE权限与自定义roles权限,可自定义转换器合并两类权限,但多数场景下设置空前缀即可解决问题。
内容的提问来源于stack exchange,提问作者Merkodanov
相关产品推荐
相关产品推荐

