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

Spring Security OAuth2资源服务器:无Token时允许匿名访问?

问题场景

需要基于Spring Security响应式栈的OAuth2 ResourceServer保护服务,但受发布计划限制,不能直接拦截无Token的请求,要实现携带Token时执行认证校验,无Token时允许匿名访问的效果。曾尝试自定义Authenticator为未认证请求返回默认用户名密码身份,但未生效。

解决方案

通过配置两个SecurityWebFilterChain实例,分别处理带Token和不带Token的请求:

@Bean
public SecurityWebFilterChain oauthSecurityWebFilterChain(ServerHttpSecurity http) {
    http
        // 仅匹配携带Authorization头的请求
        .securityMatcher(exchange -> exchange.getRequest().getHeaders().containsKey(HttpHeaders.AUTHORIZATION) ?
            ServerWebExchangeMatcher.MatchResult.match() :
            ServerWebExchangeMatcher.MatchResult.notMatch()
        )
        .csrf(ServerHttpSecurity.CsrfSpec::disable)
        .cors(Customizer.withDefaults())
        .logout(ServerHttpSecurity.LogoutSpec::disable)
        .authorizeExchange(
            authorizeExchangeSpec -> authorizeExchangeSpec
                // 指定需要认证的路径
                .pathMatchers("/api/*/app/**").authenticated()
                .pathMatchers("/api/*/admin/**").authenticated()
                .pathMatchers("/api/*/apps/**").authenticated()
                // 特定GET路径允许匿名访问
                .pathMatchers(HttpMethod.GET, "/api/v1/assets/firmware/**").permitAll()
                .anyExchange().permitAll()
        )
        // 启用JWT模式的OAuth2资源服务器
        .oauth2ResourceServer(e -> e.jwt(Customizer.withDefaults()))
        // 不存储SecurityContext,避免后续请求受影响
        .securityContextRepository(NoOpServerSecurityContextRepository.getInstance());

    return http.build();
}

/**
 * 处理无认证头的请求,兼容未添加认证的应用(后续可移除)
 * @param http ServerHttpSecurity
 * @return SecurityWebFilterChain
 */
@Bean
public SecurityWebFilterChain noAuthSecurityWebFilterChain(ServerHttpSecurity http) {
    http
        // 仅匹配不携带Authorization头的请求
        .securityMatcher(exchange -> exchange.getRequest().getHeaders().containsKey(HttpHeaders.AUTHORIZATION) ?
            ServerWebExchangeMatcher.MatchResult.notMatch() :
            ServerWebExchangeMatcher.MatchResult.match()
        )
        .csrf(ServerHttpSecurity.CsrfSpec::disable)
        .cors(Customizer.withDefaults())
        .logout(ServerHttpSecurity.LogoutSpec::disable)
        .authorizeExchange(
            authorizeExchangeSpec -> authorizeExchangeSpec
                // 所有请求允许匿名访问
                .anyExchange().permitAll()
        );

    return http.build();
}

方案说明

  • 第一个oauthSecurityWebFilterChain:仅对携带Authorization头的请求生效,启用OAuth2资源服务器的JWT认证,并配置特定路径的权限规则。
  • 第二个noAuthSecurityWebFilterChain:仅对无Authorization头的请求生效,直接允许所有请求访问,兼容未接入认证的客户端。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 15:22:42