Filter order in spring-boot

This was fixed in Spring Boot 1.2. The security chain now defaults to order 0.

It can also be set via properties:

security.filter-order=0 # Security filter chain order.

https://github.com/spring-projects/spring-boot/issues/1640


Guys from Spring helped again. See https://github.com/spring-projects/spring-boot/issues/1640 and https://jira.spring.io/browse/SEC-2730

Spring Security doesn't set an order on the Filter bean that it creates. This means that, when Boot is creating a FilterRegistrationBean for it, it gets the default order which is LOWEST_PRECEDENCE.

If you want your own Filter to go after Spring Security's you can create your own registration for Spring Security's filter and specify the order.

So the answer to my question is:

@Bean
public FilterRegistrationBean securityFilterChain(@Qualifier(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME) Filter securityFilter) {
    FilterRegistrationBean registration = new FilterRegistrationBean(securityFilter);
    registration.setOrder(Integer.MAX_VALUE - 1);
    registration.setName(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME);
    return registration;
}

@Bean
public FilterRegistrationBean userInsertingMdcFilterRegistrationBean() {
    FilterRegistrationBean registrationBean = new FilterRegistrationBean();
    UserInsertingMdcFilter userFilter = new UserInsertingMdcFilter();
    registrationBean.setFilter(userFilter);
    registrationBean.setOrder(Integer.MAX_VALUE);
    return registrationBean;
}

Here's an answer compatible with Spring Boot 2 / Spring Security 5 that will allow you to insert your filter in an arbitrary place in the filter chain.

My use case was a custom logging javax.servlet.Filter that I wanted to execute before any Spring Security filters; however the below steps should allow you to put a filter anywhere in your existing Spring filter chain:

Step 1: Find out the order of Spring filters in your existing setup.

Connect your favorite remote debugger to your application, and set a breakpoint in the doFilter(ServletRequest request, ServletResponse response) method of org.springframework.security.web.FilterChainProxy. As of Spring Security 5.1.6, that is line 311. In your debugger, find out the existing filters by inspecting this.additionalFilters. In my application, the order was something like:

0: WebAsyncManagerIntegrationFilter
1: SecurityContextPersistenceFilter
2: HeaderWriterFilter
...

Step 2: Insert your filter in the desired place using Spring's WebSecurityConfigurerAdapter and HttpSecurity

You likely already have a WebSecurityConfigurerAdapter with a @Override configure(HttpSecurity http) method. HttpSecurity exposes addFilterBefore and addFilterAfter methods to allow you to place your filter relative to an existing class in the chain. Your filter (instance) is the first argument of these methods, and the class of the filter you'd like to insert before or after is the second argument.

In my case, I wanted my custom logging filter to be first in the chain (my code snippet is Kotlin, I'll leave the Java implementation to you):

override fun configure(http: HttpSecurity) {
    http
        .addFilterBefore(MyCustomLoggingFilter(), WebAsyncManagerIntegrationFilter::class.java)
        .authorizeRequests()
        .antMatchers(
        ...
        )
}

Step 3: Profit!

Use the debugging method described in Step 1 above to verify that your filter is where you intended in the filter chain.

Hope this helps someone else out there.