Prevent Spring Boot from registering a servlet filter
I have a Spring Boot WebMVC application, and a bean that inherits from AbstractPreAuthenticatedProcessingFilter which I am explicitly adding to a specific spot in the Spring Security filter chain. My Spring Security configuration looks like this:
<http pattern="/rest/**">
<intercept-url pattern="/**" access="ROLE_USER"/>
<http-basic/>
<custom-filter after="BASIC_AUTH_FILTER" ref="preAuthenticationFilter"/>
</http>
<beans:bean id="preAuthenticationFilter" class="a.b.PreAuthenticationFilter">
<beans:property name="authenticationManager" ref="customAuthenticationManager"/>
</beans:bean>
The security configuration works. The problem is, because the PreAuthenticationFilter class inherits from AbstractPreAuthenticatedProcessingFilter, Spring Boot treats it as a general purpose servlet filter and is adding it to the servlet filter chain for all requests. I don't want this filter to be part of the filter chain for all requests. I only want it to be part of the specific Spring Security filter chain that I've configured. Is there a way to prevent Spring Boot from automatically adding the preAuthenticationFilter bean to the filter chain?
Solution 1:
By default Spring Boot creates a FilterRegistrationBean
for every Filter
in the application context for which a FilterRegistrationBean
doesn't already exist. This allows you to take control of the registration process, including disabling registration, by declaring your own FilterRegistrationBean
for the Filter
. For your PreAuthenticationFilter
the required configuration would look like this:
@Bean
public FilterRegistrationBean registration(PreAuthenticationFilter filter) {
FilterRegistrationBean registration = new FilterRegistrationBean(filter);
registration.setEnabled(false);
return registration;
}
You may also be interested in this Spring Boot issue which discusses how to disable the automatic registration of Filter
and Servlet
beans.
Solution 2:
If you want to unregister all filters at one time here's my trick:
public class DefaultFiltersBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory bf)
throws BeansException {
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) bf;
Arrays.stream(beanFactory.getBeanNamesForType(javax.servlet.Filter.class))
.forEach(name -> {
BeanDefinition definition = BeanDefinitionBuilder
.genericBeanDefinition(FilterRegistrationBean.class)
.setScope(BeanDefinition.SCOPE_SINGLETON)
.addConstructorArgReference(name)
.addConstructorArgValue(new ServletRegistrationBean[]{})
.addPropertyValue("enabled", false)
.getBeanDefinition();
beanFactory.registerBeanDefinition(name + "FilterRegistrationBean",
definition);
});
}
}
A bit more about this technique - here.
Solution 3:
If you need to disable registering 2 filters(like i did), include a name for the bean(so that they do not override):
@Bean(name = "filterRegistrationBean1")
public FilterRegistrationBean<YourFilter1> registration(YourFilter1 f1) {
FilterRegistrationBean<YourFilter1> registration = new FilterRegistrationBean<>(f1);
registration.setEnabled(false);
return registration;
}
@Bean(name = "filterRegistrationBean2")
public FilterRegistrationBean<YourFilter2> registration(YourFilter2 f2) {
FilterRegistrationBean<YourFilter2> registration = new FilterRegistrationBean<>(f2);
registration.setEnabled(false);
return registration;
}