Spring Boot 3+WebFlux中如何用Spring Security处理OAuth与非OAuth授权?
在Spring Boot 3 + WebFlux中同时支持OAuth JWT与非OAuth令牌认证
核心思路
通过扩展Spring Security WebFlux的认证体系,添加两个独立的认证过滤器,分别处理OAuth JWT令牌和非OAuth自定义令牌的校验逻辑,将它们纳入同一个安全过滤器链,实现两种认证流程的共存。
步骤1:实现非OAuth令牌的校验逻辑
自定义ReactiveAuthenticationManager,对接授权服务器的非OAuth令牌校验端点,完成令牌验证与用户信息转换:
@Component public class CustomTokenAuthenticationManager implements ReactiveAuthenticationManager { private final WebClient webClient; private final String tokenCheckEndpoint = "/auth/check-custom-token"; // 授权服务器的非OAuth令牌校验端点 public CustomTokenAuthenticationManager(WebClient.Builder webClientBuilder) { this.webClient = webClientBuilder.baseUrl("http://your-auth-server-domain").build(); } @Override public Mono<Authentication> authenticate(Authentication authentication) { String token = authentication.getCredentials().toString(); // 调用授权服务器校验令牌,转换为认证对象 return webClient.post() .uri(tokenCheckEndpoint) .header("Authorization", "Bearer " + token) .retrieve() .bodyToMono(CustomUserDetails.class) .map(userDetails -> new UsernamePasswordAuthenticationToken( userDetails.getUsername(), token, userDetails.getAuthorities() )) .onErrorResume(e -> Mono.error(new BadCredentialsException("无效的自定义令牌"))); } // 自定义用户信息DTO,根据授权服务器返回结构调整 public record CustomUserDetails(String username, List<GrantedAuthority> authorities) {} }
步骤2:配置OAuth JWT资源服务器
利用Spring Security自带的OAuth2资源服务器组件处理JWT校验,配置JWT解码器对接内部授权服务器的JWKS端点:
@Bean public JwtDecoder jwtDecoder() { return NimbusJwtDecoder.withJwkSetUri("http://your-auth-server-domain/.well-known/jwks.json").build(); } @Bean public ReactiveAuthenticationManager jwtAuthenticationManager(JwtDecoder jwtDecoder) { return new JwtAuthenticationProvider(jwtDecoder)::authenticate; }
步骤3:创建两种认证过滤器
分别为两种令牌类型创建AuthenticationWebFilter,指定对应的认证管理器与令牌提取逻辑:
非OAuth令牌过滤器
@Component public class CustomTokenAuthenticationFilter extends AuthenticationWebFilter { public CustomTokenAuthenticationFilter(CustomTokenAuthenticationManager authManager) { super(authManager); // 从Authorization头提取Bearer格式的令牌 setServerAuthenticationConverter(new ServerBearerTokenAuthenticationConverter()); } }
OAuth JWT令牌过滤器
@Component public class JwtAuthenticationFilter extends AuthenticationWebFilter { public JwtAuthenticationFilter(ReactiveAuthenticationManager jwtAuthManager) { super(jwtAuthManager); setServerAuthenticationConverter(new ServerBearerTokenAuthenticationConverter()); } }
步骤4:组装安全过滤器链
将两个过滤器加入安全链,配置端点访问规则:
@Configuration @EnableWebFluxSecurity public class SecurityConfig { private final CustomTokenAuthenticationFilter customTokenFilter; private final JwtAuthenticationFilter jwtTokenFilter; public SecurityConfig(CustomTokenAuthenticationFilter customTokenFilter, JwtAuthenticationFilter jwtTokenFilter) { this.customTokenFilter = customTokenFilter; this.jwtTokenFilter = jwtTokenFilter; } @Bean public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) { return http .csrf(ServerHttpSecurity.CsrfSpec::disable) .authorizeExchange(exchanges -> exchanges .anyExchange().authenticated() ) // 将两个过滤器加入认证环节,Spring Security会自动尝试每个过滤器直到认证成功 .addFilterAt(customTokenFilter, SecurityWebFiltersOrder.AUTHENTICATION) .addFilterAt(jwtTokenFilter, SecurityWebFiltersOrder.AUTHENTICATION) .build(); } }
关键细节说明
- 过滤器执行逻辑:两个过滤器处于同一优先级,Spring Security会依次尝试认证,只要其中一个校验通过,请求就会被放行。
- 令牌区分优化:如果两种令牌的提取规则不同(比如非OAuth令牌用自定义请求头),可以修改对应的
ServerAuthenticationConverter,避免令牌提取冲突。 - 异常统一处理:可通过配置
ServerAuthenticationEntryPoint,统一返回两种认证失败场景的响应格式。
内容的提问来源于stack exchange,提问作者Suhail Ahmed
相关产品推荐
相关产品推荐

