You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot 3.2 Webflux如何兼容两种Bearer Token认证方式?

Spring Boot 3.2 Webflux + OAuth2 Resource Server 兼容两种Bearer Token认证方案

核心思路

通过自定义Token解析器支持两种Authorization前缀(bespoke/Bearer),再用复合认证管理器实现两种Token的验证及降级逻辑——先尝试自定义Token校验,失败后自动降级到JWT校验,全程复用Spring Security原生组件,代码简洁且符合框架设计。


步骤1:自定义BearerTokenResolver支持双前缀

扩展默认的DefaultBearerTokenResolver,新增对bespoke前缀的Token提取逻辑:

import org.springframework.security.oauth2.server.resource.web.BearerTokenResolver;
import org.springframework.security.oauth2.server.resource.web.DefaultBearerTokenResolver;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

public class MultiSchemeBearerTokenResolver implements BearerTokenResolver {
    private final DefaultBearerTokenResolver defaultResolver = new DefaultBearerTokenResolver();

    @Override
    public Mono<String> resolve(ServerWebExchange exchange) {
        String authHeader = exchange.getRequest().getHeaders().getFirst("Authorization");
        // 处理自定义bespoke前缀的Token
        if (StringUtils.hasText(authHeader) && authHeader.startsWith("bespoke ")) {
            return Mono.just(authHeader.substring("bespoke ".length()));
        }
        // 降级到默认的Bearer前缀处理
        return defaultResolver.resolve(exchange);
    }
}

步骤2:实现自定义Token的认证管理器

编写处理遗留bespoke Token的认证逻辑:

import org.springframework.security.authentication.ReactiveAuthenticationManager;
import org.springframework.security.core.Authentication;
import reactor.core.publisher.Mono;

public class BespokeTokenAuthenticationManager implements ReactiveAuthenticationManager {
    @Override
    public Mono<Authentication> authenticate(Authentication authentication) {
        String token = (String) authentication.getPrincipal();
        // 替换为实际的自定义Token校验逻辑(如调用遗留校验服务、解析用户信息)
        if (isValidBespokeToken(token)) {
            // 返回认证成功的Authentication对象,示例用UsernamePasswordAuthenticationToken
            return Mono.just(new org.springframework.security.authentication.UsernamePasswordAuthenticationToken(
                    "legacy-user", null, java.util.Collections.emptyList()
            ));
        }
        // 校验失败,返回empty让后续认证管理器尝试
        return Mono.empty();
    }

    private boolean isValidBespokeToken(String token) {
        // 示例校验规则:Token以legacy-开头
        return token.startsWith("legacy-");
    }
}

步骤3:配置复合认证管理器与Security链

组合自定义认证逻辑和JWT认证逻辑,配置到Webflux Security中:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.CompositeReactiveAuthenticationManager;
import org.springframework.security.authentication.ReactiveAuthenticationManager;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.oauth2.jwt.ReactiveJwtDecoder;
import org.springframework.security.oauth2.server.resource.authentication.JwtReactiveAuthenticationManager;
import org.springframework.security.oauth2.server.resource.web.BearerTokenResolver;
import org.springframework.security.web.server.SecurityWebFilterChain;

@Configuration
@EnableWebFluxSecurity
public class SecurityConfig {
    private final ReactiveJwtDecoder jwtDecoder;

    // 注入Spring Boot自动配置的JWT解码器(需配置resourceserver.jwt相关参数)
    public SecurityConfig(ReactiveJwtDecoder jwtDecoder) {
        this.jwtDecoder = jwtDecoder;
    }

    @Bean
    public BearerTokenResolver multiSchemeBearerTokenResolver() {
        return new MultiSchemeBearerTokenResolver();
    }

    @Bean
    public ReactiveAuthenticationManager compositeAuthenticationManager() {
        BespokeTokenAuthenticationManager bespokeManager = new BespokeTokenAuthenticationManager();
        JwtReactiveAuthenticationManager jwtManager = new JwtReactiveAuthenticationManager(jwtDecoder);
        // 顺序决定降级逻辑:先试自定义Token,失败则用JWT
        return new CompositeReactiveAuthenticationManager(bespokeManager, jwtManager);
    }

    @Bean
    public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) throws Exception {
        http
                .authorizeExchange(exchanges -> exchanges.anyExchange().authenticated())
                .oauth2ResourceServer(oauth2 -> oauth2
                        .bearerTokenResolver(multiSchemeBearerTokenResolver())
                        .authenticationManager(compositeAuthenticationManager())
                );
        return http.build();
    }
}

方案优势

  1. 代码简洁:仅需扩展2个类,复用Spring Security原生组件,无需复杂自定义逻辑
  2. 天然支持降级:CompositeReactiveAuthenticationManager会自动依次尝试所有管理器,前一个校验失败则自动走下一个
  3. 适配Webflux异步模型:所有逻辑均基于Mono实现,符合非阻塞设计要求

内容的提问来源于stack exchange,提问作者DLL

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 00:32:29