WebFilter bean 在安全的 Spring Boot Webflux 应用程序中调用两次

cod*_*ent 6 spring spring-security spring-boot spring-webflux

我正在使用带有 webflux 和安全性的 Spring Boot 2.1.x。我定义了一些添加AuthenticationWebFilterMatcherSecurityWebFilterChain. 问题是,由于它们被定义为bean,因此它们也被添加到过滤器链的末尾,因此它们被执行两次。

对于 Servlet 应用程序,我们可以使用FilterRegistrationBean以下方法来避免这种情况:

@Bean
    fun someFilterRegistrationBean() {
        val frb = FilterRegistrationBean(xxx)
        frb.setEnabled(false)
        return frb
    }
Run Code Online (Sandbox Code Playgroud)

响应式应用程序的等效项是什么?

小智 1

就我而言,我必须执行 TestGatewayFilter 中存储的自定义逻辑来修改 SecurityWebFilterChain 末尾的 ServerWebExchange 对象。如果我们创建一个 TestGatewayFilter 的 bean 并让 spring 处理它,我们会发现每个请求都会调用过滤器逻辑两次。
我进行了研究,但没有找到在 spring-webflux-security 中定义 FilterRegistrationBean 的方法,但在调试时发现了一种不同的方法。

作为解决方法,我创建了 SecurityWebFilterChain 的自定义 bean,并将过滤器注入到链的末尾。为了防止 spring 两次注入这个过滤器,我们删除了创建它的 bean 的逻辑。现在,每个请求都会调用一次过滤器逻辑。

public class TestGatewayFilter implements WebFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        // To-Do logic
    }
}

@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
    http.addFilterAfter(new TestGatewayFilter(), SecurityWebFiltersOrder.AUTHORIZATION)
            .authorizeExchange()
            .anyExchange().authenticated();
    return http.build();
}
Run Code Online (Sandbox Code Playgroud)

在此,我使用addFilterAfter () 方法在链中要执行的最后一个过滤器之后添加过滤器。

ServerHttpSecurity 类提供了另外 2 个方法来在另一个过滤器之前或链中的特定位置添加过滤器。它们采用与 addFilterAfter() 方法相同的参数集,并且可以以类似的方式使用:

addFilterBefore()
addFilterAt()
Run Code Online (Sandbox Code Playgroud)

调试时,SecurityWebFilterChain 中的过滤器执行顺序如下:

  1. ServerWebExchangeReactorContextWebFilter
  2. HttpHeaderWriterWebFilter
  3. CorsWeb过滤器
  4. ReactorContextWeb过滤器
  5. 认证Web过滤器
  6. 安全上下文服务器WebExchangeWebFilter
  7. 服务器请求缓存Web过滤器
  8. 注销Web过滤器
  9. 异常翻译Web过滤器
  10. 授权Web过滤器
  11. 测试网关过滤器