Spring Boot 3.0 OAuth2资源服务器:@PreAuthorize实现用户角色API授权
核心实现步骤
1. 开启方法级安全支持
在Spring Boot启动类上添加@EnableMethodSecurity注解,启用方法级权限验证能力:
@SpringBootApplication @EnableMethodSecurity public class ResourceServerApplication { public static void main(String[] args) { SpringApplication.run(ResourceServerApplication.class, args); } }
2. 自定义Opaque Token解析器
默认的Opaque Token解析器不会自动映射自定义的user-authorities字段为Spring Security权限,需自定义解析逻辑提取该字段并转换为GrantedAuthority:
import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal; import org.springframework.security.oauth2.server.resource.introspection.NimbusOpaqueTokenIntrospector; import org.springframework.security.oauth2.server.resource.introspection.OpaqueTokenIntrospector; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.oauth2.core.DefaultOAuth2AuthenticatedPrincipal; import java.util.Collection; import java.util.Map; public class CustomOpaqueTokenIntrospector implements OpaqueTokenIntrospector { private final OpaqueTokenIntrospector delegate; public CustomOpaqueTokenIntrospector(String introspectionUri, String clientId, String clientSecret) { this.delegate = new NimbusOpaqueTokenIntrospector(introspectionUri, clientId, clientSecret); } @Override public OAuth2AuthenticatedPrincipal introspect(String token) { OAuth2AuthenticatedPrincipal principal = this.delegate.introspect(token); Map<String, Object> attributes = principal.getAttributes(); // 提取token中的user-authorities字段 Collection<String> userAuthorities = (Collection<String>) attributes.get("user-authorities"); // 返回包含自定义权限的认证主体 return new DefaultOAuth2AuthenticatedPrincipal( principal.getName(), attributes, userAuthorities.stream() .map(SimpleGrantedAuthority::new) .toList() ); } }
3. 配置资源服务器安全链
将自定义Token解析器配置到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.web.SecurityFilterChain; @Configuration public class ResourceServerConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth .anyRequest().authenticated() ) .oauth2ResourceServer(oauth2 -> oauth2 .opaqueToken(token -> token .introspector(new CustomOpaqueTokenIntrospector( "http://localhost:8080/oauth2/introspect", // 授权服务器Token introspect地址 "client", // 资源服务器client ID "client-secret" // 资源服务器client secret )) ) ); return http.build(); } }
4. 使用@PreAuthorize验证权限
在Controller方法上添加@PreAuthorize注解,通过hasAuthority匹配user-authorities中的权限值:
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class ApiController { @GetMapping("/read") @PreAuthorize("hasAuthority('READ_PRIVILEGE')") public String readResource() { return "读取资源成功"; } @GetMapping("/write") @PreAuthorize("hasAuthority('WRITE_PRIVILEGE')") public String writeResource() { return "写入资源成功"; } }
关键注意事项
- 若需使用
hasRole注解,需在转换权限时添加ROLE_前缀,例如new SimpleGrantedAuthority("ROLE_" + authority),此时注解写法为@PreAuthorize("hasRole('READ_PRIVILEGE')")。 - 确保授权服务器返回的Token中包含
user-authorities字段,且格式为字符串数组。
内容的提问来源于stack exchange,提问作者Premkumar Pallinti
相关产品推荐
相关产品推荐

