WebFilter bean 在安全的 Spring Boot Webflux 应用程序中调用了两次
Posted
技术标签:
【中文标题】WebFilter bean 在安全的 Spring Boot Webflux 应用程序中调用了两次【英文标题】:WebFilter bean invoked twice in a secured Spring Boot Webflux application 【发布时间】:2019-12-14 22:16:42 【问题描述】:我正在使用带有 webflux 和安全性的 Spring Boot 2.1.x。我定义了一些AuthenticationWebFilter
类型的bean,它们被添加到MatcherSecurityWebFilterChain
。问题是,由于它们被定义为 bean,它们也被添加到过滤器链的末尾,因此它们被执行了两次。
对于 Servlet 应用程序,我们可以使用 FilterRegistrationBean
来避免这种情况:
@Bean
fun someFilterRegistrationBean()
val frb = FilterRegistrationBean(xxx)
frb.setEnabled(false)
return frb
响应式应用程序的等价物是什么?
【问题讨论】:
【参考方案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();
在此我使用 addFilterAfter() 方法将我的过滤器添加到要在链中执行的最后一个过滤器之后。 ServerHttpSecurity 类提供了另外 2 种方法来在另一个过滤器之前或在链中的特定位置添加一个过滤器。它们采用 addFilterAfter() 方法采用的相同参数集,并且可以以类似的方式使用:
addFilterBefore()
addFilterAt()
在调试时,这是SecurityWebFilterChain中的过滤器执行顺序:
-
ServerWebExchangeReactorContextWebFilter
HttpHeaderWriterWebFilter
CorsWebFilter
ReactorContextWebFilter
身份验证WebFilter
SecurityContextServerWebExchangeWebFilter
ServerRequestCacheWebFilter
注销WebFilter
ExceptionTranslationWebFilter
AuthorizationWebFilter
TestGatewayFilter
【讨论】:
【参考方案2】:在我的情况下,我创建了自定义TokenExchangeFilter
,将org.springframework.web.server.WebFilter
实现为弹簧@Bean
。然后我尝试通过@Autowire
使用它,同时配置网络通量安全过滤器链。
@Bean
SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity http)
http
// ...
.and()
.addFilterAfter(tokenExchangeFilter, SecurityWebFiltersOrder.AUTHENTICATION);
return http.build();
这样 spring 会使用它两次。为了解决这个问题,我手动实例化了TokenExchangeFilter
(使TokenExchangeFilter
不是spring bean)。
@Bean
SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity http)
http
// ...
.and()
.addFilterAfter(new TokenExchangeFilter(authClientService), SecurityWebFiltersOrder.AUTHENTICATION);
return http.build();
【讨论】:
以上是关于WebFilter bean 在安全的 Spring Boot Webflux 应用程序中调用了两次的主要内容,如果未能解决你的问题,请参考以下文章
NoSuchMethodError: org.springframework.beans.factory.xml.XmlReaderContext.getEnvironment()Lorg/sprin