It is quite possible to include a library which is exposing a Filter/Servlet bean. Please introduce a mechanism for exclusion.

Here is the relevant section of code:

org.springframework.boot.context.embedded.ServletContextInitializerBeans#addAdaptableBeans

    private void addAdaptableBeans(ListableBeanFactory beanFactory) {
        MultipartConfigElement multipartConfig = getMultipartConfig(beanFactory);
        addAsRegistrationBean(beanFactory, Servlet.class, new ServletRegistrationBeanAdapter(multipartConfig));
        addAsRegistrationBean(beanFactory, Filter.class, new FilterRegistrationBeanAdapter());
        for (Class<?> listenerType : ServletListenerRegistrationBean.getSupportedTypes()) {
            addAsRegistrationBean(beanFactory, EventListener.class, (Class<EventListener>) listenerType, new ServletListenerRegistrationBeanAdapter());
        }
    }

2171 is also related to this issue.

Comment From: philwebb

Do you have any specific examples of libraries that are adding Filters/Servlets?

Comment From: philwebb

OK, ignore that last comment. I see #2171 is related.

Comment From: dsyer

There is a mechanism for exclusion, if you have an immediate problem and just need the solution. You create a *RegistrationBean and set it to enabled=false.

Comment From: cemo

@dsyer, Please correct me If I am wrong. You mean that I should add another FilterRegistrationBean with same filter name. This will cause skipping new created FilterRegistrationBean but not actual one. Right?

Comment From: dsyer

That wasn't what I meant. Why not use the enabled flag (it's just a Boolean property in the FRB)?

Comment From: cemo

Because it is not a FilterRegistrationBean. It is a plain Filter.

@Bean(name=AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
    public Filter springSecurityFilterChain() throws Exception {
        boolean hasConfigurers = webSecurityConfigurers != null && !webSecurityConfigurers.isEmpty();
        if(!hasConfigurers) {
            throw new IllegalStateException("At least one non-null instance of "+ WebSecurityConfigurer.class.getSimpleName()+" must be exposed as a @Bean when using @EnableWebSecurity. Hint try extending "+ WebSecurityConfigurerAdapter.class.getSimpleName());
        }
        return webSecurity.build();
    }

Here is the relevant code which is causing trouble. This piece of code is from Spring Security. Spring Security is exposing a Filter for internal usage. However Spring Boot is catching it and trying to register as a Servlet Api Filter.

Comment From: dsyer

It's not really "for internal use" though is it? It's for your application security. If you don't want it, why is Spring Security on the classpath?

Comment From: dsyer

And there's nothing to stop you creating a FilterRegistrationBean and injecting that Filter if you need to change its behaviour. You know its type and bean id.

Comment From: cemo

I have not noticed that you had already added seen beans check. This is disabling existing filters as I stated in issue description.

But there is still a problem. Spring's DelegatingFilterProxy is binding filter at init phase of filter. Your check is invalid for this situation. Maybe checking filter name is an option? (By the way Servlet Api is already checking filter names. In case a duplicated already configured same name filter, It is skipping it. )

Comment From: dsyer

OK so we appear to have agreed that there is already a mechanism in place for disabling existing filters. Maybe we need more documentation?

I don't get the last point about the "init" phase (there is no "init" phase for a Filter in a spring boot app - just the normal spring lifecycle). If you have a specific problem you are trying to solve, maybe you can explain it better with a small sample project?

Comment From: cemo

+1 for more documentation.

I meant org.springframework.web.filter.DelegatingFilterProxy#initFilterBean method.

I am migrating a legacy application, I have to use FilterRegistrationBean + DelegatingFilterProxy currently. In case of a direct usage of FilterRegistrationBean + Security Filter, I am having issues. This is probably related to our application but at least currently I do not have any problem.

I believe that disabling mechanism of a filter is not complete without DelegatingFilterProxy support. In order to support such kind of filters, checking filter name might be a good idea.

Comment From: wilkinsona

Someone on Stack Overflow with the same problem

Comment From: cemo

What about DelegatingFilterProxy filters?

Comment From: dsyer

What about them? They are just filters.

Comment From: cemo

Could you show me an example how would you disable a DelegatingFilterProxy filter please?

Comment From: dsyer

It's the same as the example Andy added to the docs:

@Bean
public FilterRegistrationBean registration() {
        DelegatingFilterProxy filter = filter(); // or inject it with a @Qualifier
    FilterRegistrationBean registration = new FilterRegistrationBean(filter);
    registration.setEnabled(false);
    return registration;
}

Comment From: hohwille

Works like a charm. I had a custom solution that I used prior to this, for those who do not like too much spring magic you can also use it:

public interface HttpServletFilter {
  void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
      throws IOException, ServletException;
}
public class HttpServletFilterWrapper implements Filter {
  private final HttpServletFilter filter;

  public HttpServletFilterWrapper(HttpServletFilter filter) {
    super();
    this.filter = filter;
  }

  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {
    this.filter.doFilter((HttpServletRequest) request, (HttpServletResponse) response, chain);
  }

  @Override
  public void init(FilterConfig filterConfig) throws ServletException {  }

  @Override
  public void destroy() {  }
}

Then in your @Named annotated bean implement HttpServletFilter instead of Filter and in your spring security config do something like this:

  @Inject
  private MyFilter myFilter; // your filter that implements HttpServletFilter

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.foo().bar() //
        and().addFilterAfter(new HttpServletFilterWrapper(this.myFilter), LogoutFilter.class);
  }

Comment From: chris922

Topic is quite old but was still relevant for us. I think we had the same issue @cemo described, the securityFilterChain was executed twice.

I first saw this in the logs

08:51:54.325 [http-nio-8080-exec-1] DEBUG org.springframework.security.web.FilterChainProxy  - /xyz at position 9 of 9 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
08:51:54.326 [http-nio-8080-exec-1] DEBUG org.springframework.security.web.access.intercept.FilterSecurityInterceptor  - Public object - authentication not attempted
08:51:54.327 [http-nio-8080-exec-1] DEBUG org.springframework.security.web.FilterChainProxy  - /xyz reached end of additional filter chain; proceeding with original chain
08:51:54.327 [http-nio-8080-exec-1] DEBUG org.springframework.security.web.FilterChainProxy  - /xyz at position 1 of 9 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter`

And then also in the startup-phase

09:05:03.204 [localhost-startStop-1] INFO  org.springframework.boot.web.servlet.DelegatingFilterProxyRegistrationBean  - Mapping filter: 'springSecurityFilterChain' to: [/*]
09:05:10.040 [localhost-startStop-1] INFO  org.springframework.boot.web.servlet.FilterRegistrationBean  - Mapping filter: 'org.springframework.security.filterChainProxy' to: [/*]

Thanks for the information here to find the solution.

For the sake of completeness here the solution via XML configuration

<bean class="org.springframework.boot.web.servlet.FilterRegistrationBean">
    <property name="filter" ref="springSecurityFilterChain" />
    <property name="enabled" value="false" />
</bean>

I debugged a lot to find this and also tried various configuration and found out that this issue happens when a <security:http> configuration is there without auto-config enabled (so when there is just one entry inside this tag. Therefore I think this is a bigger issue when using Spring Boot and Spring Security and should be mentioned inside the Spring Security documentation explicitly.

Comment From: Ziemowit

@chris922 Your solution helped me! Yeah! I have spent whole day to figure out what is happening :(

I had similar problem => moving legacy spring application to Spring Boot with security configuration defined in xml file.

Because of some reason 2 spring security filter chains were created by Spring Boot and my custom filters were called twice per each request.

(Debug view on application filters chain):

...
ApplicationFilterConfig[name=springSecurityFilterChain, filterClass=org.springframework.boot.web.servlet.DelegatingFilterProxyRegistrationBean$1]
ApplicationFilterConfig[name=org.springframework.security.filterChainProxy, filterClass=org.springframework.security.web.FilterChainProxy]
...

After applying your solution my application works well! Now the question is if it is some bug in my application that 2 spring security filter chains are created or it is some problem between xml config <=> Spring Boot?

Now I am only thinking loudly... Maybe it is becuase:

a) Spring Security documentation claims:

If you use an element within your application, a FilterChainProxy bean named "springSecurityFilterChain" is created and the configuration within the element is used to build a filter chain within FilterChainProxy

So as we have spring security configuration in xml we have tag defined there. So "springSecurityFilterChain" is created.

b) As Spring Boot find Spring-Security on classpath it creates the 2nd one security chain during auto-configuration.

As a result of points a) and b) we have 2 security filter chains in application.

Comment From: lxnx0

I'm having the same problem today.

For unknown reason, I keep on getting NullPointerException without any clue. Until I found out that the Security Filter was ran twice.

Following is my solution :

@Bean
public FilterRegistrationBean filterRegistrationBean() throws Exception {
    FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
    filterRegistrationBean.setEnabled(false);
    filterRegistrationBean.setFilter(authenticationTokenFilterBean());
    return filterRegistrationBean;
}

Comment From: lopiter

is this issue is closed?? i got same problem..

see org.springframework.boot.web.servlet.ServletContextInitializerBeans class source..

private void addAdaptableBeans(ListableBeanFactory beanFactory) {
        MultipartConfigElement multipartConfig = this.getMultipartConfig(beanFactory);
        this.addAsRegistrationBean(beanFactory, Servlet.class, new ServletContextInitializerBeans.ServletRegistrationBeanAdapter(multipartConfig));
        this.addAsRegistrationBean(beanFactory, Filter.class, new ServletContextInitializerBeans.FilterRegistrationBeanAdapter(null));
        Iterator var3 = ServletListenerRegistrationBean.getSupportedTypes().iterator();

        while(var3.hasNext()) {
            Class listenerType = (Class)var3.next();
            this.addAsRegistrationBean(beanFactory, EventListener.class, listenerType, new ServletContextInitializerBeans.ServletListenerRegistrationBeanAdapter(null));
        }

    }

bean class that implements javax.servlet.Filter interface is registered to filter automatically

Comment From: wilkinsona

is this issue is closed?

Yes. It says so at the top of the page

bean class that implements javax.servlet.Filter interface is registered to filter automatically

That's by design. Please read the documentation to learn how to disable that registration.

Comment From: HappySnoopy

Sorry to bother everyone, but the FilterRegistrationBean did not work for me.

My configuration is :

    @Bean
    public FilterRegistrationBean afterAuthenticatedProcessingFilter(
            @Autowired RedisTool<String, String> redisTool,
            @Autowired CaptchaSettingServiceImpl captchaSettingService,
            @Autowired SystemSettingHelper systemSettingHelper) {
        FilterRegistrationBean registration = new FilterRegistrationBean();

        AfterAuthenticatedProcessingFilter filter = new AfterAuthenticatedProcessingFilter();
        filter.setRedisTool(redisTool);
        filter.setCaptchaSettingService(captchaSettingService);
        filter.setSystemSettingHelper(systemSettingHelper);
        registration.setFilter(filter);
        registration.setName("afterAuthenticatedProcessingFilter");
        registration.setEnabled(false);
        return registration;
    }

and the AfterAuthenticatedProcessingFilter is:

public class AfterAuthenticatedProcessingFilter extends GenericFilterBean {
    // ignore the implement codes
}

but when my application bootstap, an exception was throwed and the root cause is:

Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.security.web.DefaultSecurityFilterChain#4': Unsatisfied dependency expressed through constructor parameter 1: Could not convert argument value of type [java.util.ArrayList] to required type [java.util.List]: Failed to convert value of type 'java.util.ArrayList' to required type 'java.util.List'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'org.springframework.boot.web.servlet.FilterRegistrationBean' to required type 'javax.servlet.Filter': no matching editors or conversion strategy found at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:723) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE] at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:189) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1193) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE] some other logs

so, have anyone seen a similar problem? and could anyone give me some sugguestion? thanks a lot!

Comment From: snicoll

@winters1224 please ask questions on stackoverflow.

Comment From: HappySnoopy

@snicoll OK,thanks.

Comment From: mbhave

@OrangeDog This issue is closed. If you have an enhancement request, please create a new issue.

Comment From: neshtaMedia

When migrating from legacy code (with a lot of XML configuration), it would be great to be able to disable automatic registration of filters and servlets. This is exactly what I'm doing now and I have to disable a lot of filters with FilterRegistrationBean.setEnabled(false)

Comment From: wilkinsona

@neshtaMedia I believe you could do that with a custom subclass of org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext that overrides getServletContextInitializerBeans().