Spring Boot 3.1.2 安全过滤器链在返回类型为响应式时调用两次

问题描述 投票:0回答:1

当从 Spring Boot 3.1.2 Web MVC 控制器返回反应类型(例如

Mono<T>
)时,安全过滤器链将被调用两次,一次在调用 API 方法之前,然后再次调用。

当返回类型为非响应式时,不会发生这种情况。

为了重现,这里有一个最小的可重现示例:

  1. 使用 Spring Initialzr 创建 Spring Boot 3.1.2 项目,包括 web、webflux 和安全依赖项。

  2. 添加仅记录的自定义过滤器:

    public class CustomFilter extends GenericFilterBean {
    
      @Override
      public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {
    
        logger.info("Custom filter called");
        chain.doFilter(request, response);
      }
    }
    
  3. 添加安全过滤器链bean来添加过滤器:

    @Configuration
    public class CustomWebSecurityConfigurerAdapter {
    
      @Bean
      public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.addFilterAfter(new CustomFilter(), BasicAuthenticationFilter.class);
        return http.build();
      }
    }
    
  4. 添加 REST API 进行测试:

    @RestController
    public class RestApi {
    
      @GetMapping("/hello-reactive")
      Mono<String> helloReactive() {
        return Mono.just("hello world");
      }
    
      @GetMapping("/hello")
      String hello() {
        return "hello world";
      }
    }
    

现在我们可以展示问题了:

首先是非反应式方法:

$ curl localhost:8080/hello
hello world

记录:

2023-08-11T10:30:02.232+01:00  INFO 24000 --- [nio-8080-exec-3] com.example.demo.CustomFilter            : Custom filter called

现在是反应式方法:

$ curl localhost:8080/hello-reactive
hello world

记录:

2023-08-11T10:32:12.776+01:00  INFO 24000 --- [nio-8080-exec-6] com.example.demo.CustomFilter            : Custom filter called
2023-08-11T10:32:12.779+01:00  INFO 24000 --- [nio-8080-exec-6] com.example.demo.CustomFilter            : Custom filter called
java spring-boot spring-security spring-webflux
1个回答
0
投票

为了不让上述安全自定义过滤器应用两次,您可以简单地允许 SecurityFilterChain 中的所有异步调度程序。通过此设置,只有请求调度程序才会应用自定义过滤器。

 .... 
 http
     .authorizeHttpRequests(authorizeHttpRequestsCustomizer -> {
       authorizeHttpRequestsCustomizer
           .dispatcherTypeMatchers(DispatcherType.ASYNC).permitAll()
           ...
     });

以下 github 问题可能值得阅读以了解其他替代方案:https://github.com/spring-projects/spring-security/issues/11962

© www.soinside.com 2019 - 2024. All rights reserved.