Spring Security:从JWT生成Authentication并映射Claims至权限
Spring Security JWT资源服务器实现方法级授权
1. 开启方法级安全支持
在你的Spring Security配置类上添加@EnableMethodSecurity(prePostEnabled = true)注解,开启@PreAuthorize等方法级授权注解的支持:
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; @EnableWebSecurity @EnableMethodSecurity(prePostEnabled = true) public class ResourceServerConfig { // 现有配置代码... }
2. 自定义JWT权限转换器
实现JWT Claims到Spring Security权限的映射,自定义转换器从JWT的Claims中提取权限信息并转换为GrantedAuthority对象:
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 CustomJwtAuthenticationConverter implements Converter<Jwt, Collection<GrantedAuthority>> { @Override public Collection<GrantedAuthority> convert(Jwt jwt) { // 从JWT Claims中获取权限列表,此处假设权限存储在"roles"字段下,可根据实际结构调整 List<String> roles = jwt.getClaimAsStringList("roles"); // 转换为Spring Security标准权限对象,如需ROLE_前缀可在此添加 return roles.stream() .map(role -> new SimpleGrantedAuthority("ROLE_" + role)) .collect(Collectors.toList()); } }
3. 配置资源服务器使用自定义转换器
在资源服务器Security配置中,将自定义转换器注入并绑定到JWT认证流程:
import org.springframework.context.annotation.Bean; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter; import org.springframework.security.web.SecurityFilterChain; public class ResourceServerConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth .anyRequest().authenticated() ) .oauth2ResourceServer(oauth2 -> oauth2 .jwt(jwt -> jwt .jwtAuthenticationConverter(jwtAuthenticationConverter()) ) ); return http.build(); } @Bean public JwtAuthenticationConverter jwtAuthenticationConverter() { JwtAuthenticationConverter converter = new JwtAuthenticationConverter(); converter.setJwtGrantedAuthoritiesConverter(new CustomJwtAuthenticationConverter()); return converter; } // 其他现有Bean配置... }
4. 在接口上使用方法级授权注解
现在可以在Controller方法上通过@PreAuthorize注解实现角色校验:
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class DemoController { @GetMapping("/admin") @PreAuthorize("hasRole('ADMIN')") public String adminOnly() { return "管理员专属内容"; } @GetMapping("/user") @PreAuthorize("hasAnyRole('USER', 'ADMIN')") public String userOrAdmin() { return "普通用户或管理员可访问"; } }
注意事项
- 需确保JWT的Claims中包含对应权限字段,字段名需与转换器中的配置一致
- 若你的角色定义无需
ROLE_前缀,可直接返回new SimpleGrantedAuthority(role) - 若JWT中权限以逗号分隔的字符串存储,需先拆分字符串再转换为权限列表
内容的提问来源于stack exchange,提问作者Jordi
相关产品推荐
相关产品推荐

