According to the documentation all WebFilter Beans are added to each exchange.

When using multiple SecurityWebFilterChains that share some, but not all available WebFilter I found no way to declare such WebFilter as Beans. Instead I have to define them locally in the method creating the SecurityWebFilterChain.

In the Servlet-world there is a way via FilterRegistrationBean to prevent the addition of a Filter like this.

@Bean
public FilterRegistrationBean<OncePerRequestFilter> myFilterRegistration(
        @Qualifier("myCustomFilter") OncePerRequestFilter filter) {
  FilterRegistrationBean<OncePerRequestFilter> reg = new FilterRegistrationBean<>(filter);
  reg.setEnabled(false);
  return reg;
}

Please provide a similar functionality for WebFilter

Comment From: wilkinsona

Spring Boot has quite limited control over this. The gathering of all of the WebFilter beans from the application context is done by Spring Framework's WebHttpHandlerBuilder when Boot initialises it using the application context:

https://github.com/spring-projects/spring-boot/blob/df67dec561e1cd9b21c3110c6b417c7e7f18cacb/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/HttpHandlerAutoConfiguration.java#L62-L71

You could try defining your own HttpHandler bean which will cause the bean above to back off. One possibility would be to use the builder's filters(Consumer<List<WebFilter>> consumer) and remove from the list those filters found in the application context that you don't want to be included.

If the above works for you, we could consider a WebHttpHandlerBuilderCustomizer callback interface that would allow you to customize the auto-configured builder and avoid the need to define your own HttpHandler.

Comment From: mpapenbr

Thanks for the hint, using the filters(Consumer<List<WebFilter>> consumer) produces the wanted results. A customizer callback would be nice.

...
@Bean
Consumer<List<WebFilter>> globalFilterCustomizer() {
        // for demo purpose: I don't want any filters in the global chain that contain CustomFilter in the class name
    Predicate<WebFilter> isCustomFilter = f -> f.getClass().getName().contains("CustomFilter");
    return filters -> filters.removeIf(isCustomFilter);
}

@Bean
public HttpHandler httpHandler(
                ObjectProvider<WebFluxProperties> propsProvider,
        Consumer<List<WebFilter>> globalFilterCustomizer) {
    HttpHandler httpHandler = WebHttpHandlerBuilder
                .applicationContext(this.applicationContext)
        .filters(globalFilterCustomizer)
                .build();
    WebFluxProperties properties = propsProvider.getIfAvailable();
    if (properties != null && StringUtils.hasText(properties.getBasePath())) {
        Map<String, HttpHandler> handlersMap = Collections.singletonMap(properties.getBasePath(), httpHandler);
        return new ContextPathCompositeHandler(handlersMap);
    }
    return httpHandler;
}
... 

For more details see this demo repository

Comment From: scottfrederick

Closing in favor of #39467