Spring Security响应式WebFilterChainProxy仅调用单个过滤器链

5
我需要在基于Webflux的应用程序中添加安全性,有一些要求使我需要添加多个过滤器链。然而,目前的WebFilterChainProxy实现使用Flux.filterWhen(...),如果我正确阅读文档的话,它只会返回链中的第一个匹配项。
鉴于上述情况,我有三个问题:
1. 我的React知识非常有限,有人能确认一下我对filterWhen的理解是否正确吗? 2. 如果是这样的话,有人可以建议一种在新的Spring Security 5反应模型中使多个过滤器链工作的方法吗? 3. 如果我误解了filterWhen方法的工作原理,有人能提出任何建议,为什么只处理我的一个过滤器链?
我通过使用@Order注释的多个配置方法将过滤器添加到链中,类似于下面的代码块。
@Configration
@EnableWebFluxSecurity
public class SecurityConfig
    ...
    @Bean
    @Order(1)
    SecurityWebFilterChain chain1(ServerHttpSecurity http) {
        return http.httpBasic().disable()......
    }

    @Bean
    @Order(2)
    SecurityWebFilterChain chain2(ServerHttpSecurity http) {
        return http.httpBasic().disable()......
    }

    @Bean
    @Order(3)
    SecurityWebFilterChain chain3(ServerHttpSecurity http) {
        return http.httpBasic().disable()......
    }
    ...
}

当我调试应用程序时,我可以看到所有三个过滤器都已添加到WebFilterChainProxy,但我只能获得一个匹配的过滤器。我需要找到一种返回所有匹配过滤器的方法。
请问有人能帮忙吗?

看起来 https://github.com/spring-projects/spring-security/issues/5395 是 Spring Security 上述问题的 bug。 - KMeda
2个回答

3

我最终通过使用ServerWebExchangeMatchers解决了这个问题。我的用例涉及在访问Spring Actuator端点时启用基本身份验证,而在其他路径上不进行身份验证。我通过以下代码实现了这一点:

@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity httpSecurity) 
{
    httpSecurity
            .csrf().disable()
            .logout().disable()
            .formLogin().disable();


 httpSecurity.securityMatcher(ServerWebExchangeMatchers.pathMatchers("/actuator/**"))
            .httpBasic()
            .and()
            .authorizeExchange()
            .pathMatchers("/actuator/**")
            .hasRole(ACTUATOR_ADMIN_ROLE);

    return httpSecurity.build();
}

最终,我实际上做了非常相似的事情,但没有发布为答案,因为它实际上是微妙不同的。使用您描述的方法(以及我实施的方法),仅当我真正想要应用多个时,才会应用单个过滤器链。我现在会添加自己的答案,但感谢您的回复! - andye

2

我在这里回答自己的问题,希望能帮助其他人更好地理解。

  1. 我的React知识非常有限,有人能确认一下我的filterWhen方法的理解是否正确吗?

是的,我的理解是正确的,Flux.filterWhen(...)只会返回第一个匹配项。

  1. 如果是这样,有人能建议一种在新的Spring Security 5反应模型中使多个过滤器链工作的方法吗?

多个过滤器链在Spring Security 5的响应式部分中“可以”直接使用,但它们只以相互排斥的方式工作,例如,给定使用Flux.filterWhen(...),只会应用单个过滤器。

  1. 如果我误解了filterWhen方法的工作原理,有人能提出任何建议,为什么只处理一个过滤器链?

请参见上面第2个问题的答案。

从更广泛的角度来看,我的最初要求是具有多个链,其中将应用多个链,但考虑到已经概述的限制,这根本不可能。我不得不修改我们正在做的内容,使其与框架配合而不是反对它。

我们仍然需要多个过滤器链,因为不同流程的安全要求不同,我们最终使用了相同的ServerWebExchangeMatchers,并以类似于@KRam答案中描述的方式使用。


那么你如何在一个端点上支持多种身份验证方法呢?例如,我想通过提供 JWT 或使用用户 ID 和密码来访问 /api 端点。 - mbluke
@mbluke,我的情况与你所寻找的不同,而且我已经不在这个领域了,但我认为你可以通过扩展AuthenticationWebFilter并通过setAuthenticationConverter方法传递自定义验证器来实现。在您的自定义验证器中,您可以根据请求头信息确定要使用的方法,并委托给特定的实现。 - andye

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接