首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >禁用WebFilter的自动注册

禁用WebFilter的自动注册
EN

Stack Overflow用户
提问于 2021-03-19 20:05:04
回答 1查看 241关注 0票数 0

在一个spring-Boot2.4应用程序中,我有两个SecurityWebFilterChain,对于其中的一个,我想通过addFilterBefore()添加一些WebFilter

代码语言:javascript
复制
@Configuration
@EnableWebFluxSecurity
class WebSecurityConfig {

    @Bean
    fun filter1(service: Service): WebFilter = Filter1(service)

    @Bean
    fun filter2(component: Component): WebFilter = Filter2(component)

    @Bean
    @Order(1)
    fun apiSecurityConfiguration(
        http: ServerHttpSecurity,
        filter1: WebFilter,
        filter2: WebFilter
    ): SecurityWebFilterChain = http
        .securityMatcher(pathMatchers("/path/**"))
        .addFilterBefore(filter1, SecurityWebFiltersOrder.AUTHENTICATION)
        .addFilterAt(filter2, SecurityWebFiltersOrder.AUTHENTICATION)
        .build()

    @Bean
    @Order(2)
    fun actuatorSecurityConfiguration(
        http: ServerHttpSecurity,
        reactiveAuthenticationManager: ReactiveAuthenticationManager
    ): SecurityWebFilterChain = http
        .securityMatcher(pathMatchers("/manage/**"))
        .authenticationManager(reactiveAuthenticationManager)
        .httpBasic { }
        .build()
}

但是,由于这些WebFilter是作为bean创建的,它们会自动注册并应用于所有请求,看起来像是在安全链之外。

对于servlet筛选器,可以使用FilterRegistrationBean禁用此注册(请参阅spring-boot documentation)。

reactive WebFilter有没有类似的方法,或者我必须在这些过滤器中添加额外的URL过滤?

EN

回答 1

Stack Overflow用户

发布于 2021-03-21 17:45:23

为了找到解决方案,我们首先必须更深入地研究spring是如何工作的,以及它的内部结构。

所有WebFilter类型的bean都会自动添加到主web处理筛选器链中。

有关该主题的信息,请参阅spring boot documentation

在应用程序上下文中找到的

WebFilter beans将自动用于过滤每个交换。

因此,即使您希望它们仅应用于特定的spring-security过滤器链,也会发生这种情况。

(我的意思是,重用FilterWebFilter接口,而不使用具有相同签名的特定于安全的东西,这是spring安全性的一点缺陷。)

在代码中,相关部分在spring-web的WebHttpHandlerBuilder

代码语言:javascript
复制
public static WebHttpHandlerBuilder applicationContext(ApplicationContext context) {
    // ...

    List<WebFilter> webFilters = context
            .getBeanProvider(WebFilter.class)
            .orderedStream()
            .collect(Collectors.toList());
    builder.filters(filters -> filters.addAll(webFilters));

    // ...
}

然后在spring-boot的HttpHandlerAutoConfiguration中调用它来创建主HttpHandler。

代码语言:javascript
复制
@Bean
public HttpHandler httpHandler(ObjectProvider<WebFluxProperties> propsProvider) {
    HttpHandler httpHandler = WebHttpHandlerBuilder.applicationContext(this.applicationContext).build();
    // ...
    return httpHandler;
}

为了防止将这些过滤器应用于所有交换,可以简单地不将它们创建为bean并手动创建它们,正如上面的注释中所建议的那样。则BeanProvider不会找到它们,也不会将它们添加到HttpHandler中。但是,您离开了IoC国家/地区并丢失了过滤器的自动配置。当这些过滤器变得更复杂,或者当你有很多过滤器时,这并不理想。

因此,我的解决方案是为我的应用程序手动配置一个HttpHandler,这不会将我的特定于安全的过滤器添加到全局过滤器链中。

为此,我首先为我的过滤器声明了一个marker interface

代码语言:javascript
复制
interface NonGlobalFilter

class MySecurityFilter : WebFilter, NonGlobalFilter {
  // ...
}

然后,在创建自定义HttpHandler的位置需要一个配置类。方便的是,WebHttpHandlerBuilder有一个带有消费者的method to manipulate its filter list

这将阻止spring-boot使用来自HttpHandlerAutoConfiguration的自己的HttpHandler,因为它是用@ConditionalOnMissingBean(HttpHandler.class)注释的。

代码语言:javascript
复制
@Configuration
class WebHttpHandlerConfiguration(
    private val applicationContext: ApplicationContext
) {
    @Bean
    fun httpHandler() = WebHttpHandlerBuilder
        .applicationContext(applicationContext)
        .filters {
            it.removeIf {
                webFilter -> webFilter is NonGlobalFilter
            }
        }
        .build()
}

就是这样!和往常一样,spring提供了许多开箱即用的有用默认设置,但当它阻碍您的方式时,将有一种方法可以根据需要对其进行调整。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66707864

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档