Broadleaf Microservices
  • v1.0.0-latest-prod

Register Security Filters

Disable Container Registration for Security Filter Beans

When adding a new Filter to a SecurityFilterChain, it is important that the Filter is not registered to the container (e.g., Tomcat). The filters registered to the container run outside the SecurityFilterChain. By default, Spring Boot will register all Filter beans with the container. Therefore, care should be taken when adding new security filters to either not register the object as a bean, or wrap it in a FilterRegistrationBean that explicitly disables the container registration.

See the "Note" in Web Security section of Spring Security Architecture.

In addition to the security considerations, a security Filter bean that gets registered with the container would execute twice because it would be registered in both the default filter chain and the security filter chain. This could lead to unwanted behavior.

Also see Spring documentation section Disable Registration of a Servlet or Filter

Only for security filters

This advice about using FilterRegistrationBean to disable registration only applies to Filters that will be used in a SecurityFilterChain. If the Filter is not related to security and should run in the normal filter chain, it can be declared as a normal bean. Spring Boot will automatically register it with the servlet container.

Examples version 1.x

Adding a security filter that is not a bean

The simplest way is to instantiate the new filter in-line when adding it to the security filter chain.

AuthenticationService 1.x Example
class ExampleWebConfig extends WebSecurityConfigurerAdapter {
    protected void configure(HttpSecurity http) throws Exception {
        http.addFilter(new MyCustomSecurityFilter());
    }
}

Instantiation logic could be in a separate method as well.

AuthenticationService 1.x Example
class ExampleWebConfig extends WebSecurityConfigurerAdapter {
    protected void configure(HttpSecurity http) throws Exception {
        http.addFilter(myCustomSecurityFilter());
    }

    protected MyCustomSecurityFilter myCustomSecurityFilter() {
        return new MyCustomSecurityFilter();
    }
}

Adding a security filter that is a bean

There are a variety of reasons that you might want your filter to be a bean. For example, Autowiring fields. Regardless of which Configuration class defines the filter or how it is injected, a FilterRegistrationBean should be created.

AuthenticationService 1.x Example
class ExampleWebConfig extends WebSecurityConfigurerAdapter {

    protected void configure(HttpSecurity http) throws Exception {
        http.addFilter(myCustomSecurityFilter());
    }

    @Bean
    protected MyCustomSecurityFilter myCustomSecurityFilter() {
        return new MyCustomSecurityFilter();
    }

    @Bean
    public FilterRegistrationBean<MyCustomSecurityFilter> myCustomSecurityFilterRegistration (MyCustomSecurityFilter filter) {
        FilterRegistrationBean<MyCustomSecurityFilter> filterRegistrationBean = new FilterRegistrationBean<>();
        filterRegistrationBean.setFilter(filter);
        filterRegistrationBean.setEnabled(false);
        return filterRegistrationBean;
    }
}
AuthenticationService 1.x Example
class ExampleWebConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private MyCustomSecurityFilter myCustomSecurityFilter;

    protected void configure(HttpSecurity http) throws Exception {
        http.addFilter(myCustomSecurityFilter);
    }
}

@Configuration
class ExampleAdditionalConfig {
    @Bean
    protected MyCustomSecurityFilter myCustomSecurityFilter() {
        return new MyCustomSecurityFilter();
    }

    @Bean
    public FilterRegistrationBean<MyCustomSecurityFilter> myCustomSecurityFilterRegistration (MyCustomSecurityFilter filter) {
        FilterRegistrationBean<MyCustomSecurityFilter> filterRegistrationBean = new FilterRegistrationBean<>();
        filterRegistrationBean.setFilter(filter);
        filterRegistrationBean.setEnabled(false);
        return filterRegistrationBean;
    }
}

Examples version 2.x

These examples use LateAuthenticationSecurityChainCustomizer to modify the HttpSecurity object. See Authentication Security Chain Customizers for more information.

Adding a security filter that is not a bean

The simplest way is to instantiate the new filter in-line when adding it to the security filter chain.

AuthenticationService 2.x Example
@Configuration
class ExampleAdditionalConfig {
    @Bean
    protected LateAuthenticationSecurityChainCustomizer myCustomFilterCustomizer(HttpSecurity http) throws Exception {
        http.addFilter(new MyCustomSecurityFilter());
    }
}

Instantiation logic could be in a separate method as well.

AuthenticationService 2.x Example
@Configuration
class ExampleAdditionalConfig {
    @Bean
    protected LateAuthenticationSecurityChainCustomizer myCustomFilterCustomizer(HttpSecurity http) throws Exception {
        http.addFilter(myCustomSecurityFilter());
    }

    protected MyCustomSecurityFilter myCustomSecurityFilter() {
        return new MyCustomSecurityFilter();
    }
}

Adding a security filter that is a bean

There are a variety of reasons that you might want your filter to be a bean. For example, Autowiring fields. Regardless of which Configuration class defines the filter or how it is injected, a FilterRegistrationBean should be created.

AuthenticationService 2.x Example
@Configuration
class ExampleAdditionalConfig {

    @Autowired
    private MyCustomSecurityFilter myCustomSecurityFilter;

    @Bean
    protected LateAuthenticationSecurityChainCustomizer myCustomFilterCustomizer(HttpSecurity http) throws Exception {
        http.addFilter(myCustomSecurityFilter);
    }
}

@Configuration
class ExampleFilterConfig {
    @Bean
    protected MyCustomSecurityFilter myCustomSecurityFilter() {
        return new MyCustomSecurityFilter();
    }

    @Bean
    public FilterRegistrationBean<MyCustomSecurityFilter> myCustomSecurityFilterRegistration (MyCustomSecurityFilter filter) {
        FilterRegistrationBean<MyCustomSecurityFilter> filterRegistrationBean = new FilterRegistrationBean<>();
        filterRegistrationBean.setFilter(filter);
        filterRegistrationBean.setEnabled(false);
        return filterRegistrationBean;
    }
}

Adding a non-security filter

A Filter that is not used for security can be declared like a normal bean. Spring boot will automatically register it with the container, and it will run with the servlet filter chain.

@Configuration
class ExampleAdditionalConfig {
    @Bean
    protected MyCustomFilter myCustomFilter() {
        return new MyCustomFilter();
    }
}