Add Custom Filter Spring boot security

In this article, we will learn how to add our own filter and add it to spring security filter chain at specified location with example code.

What is a filter?
A filter as the name suggests, is used to filter out requests based on some logic. Any request that arrives to the application is received by a filter.
The filter may then execute some logic and allow the request to forward to some other filter, forward to application or return back to the client.

An application may have more than one filters which constitutes a filter chain. When there are more than one filters, one filter is executed after another in a pre-defined order.

Below is the list of filters in spring security filter chain, which are executed in the same order

WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
CsrfFilter
LogoutFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
SessionManagementFilter
ExceptionTranslationFilter

Create Custom Filter
To create your own filter, follow below steps
1. Create a class that extends javax.servlet.Filter interface.
2. Implement doFilter() method from above interface. doFilter() has below signature

public void doFilter(ServletRequest request, 
      ServletResponse response, FilterChain chain)
      throws IOException, ServletException { }

doFilter() accepts 3 arguments.
A. First is the request object,
B. Second is response and
C. third is the filter chain.

FilterChain object is used to invoke next filters in the servlet container’s chain of filters.

3. At the end of doFilter() method, invoke doFilter() method of FilterChain passing it the request and response objects so that the next configured filter in the chain in invoked.

Spring security custom filter example
Below is an example of a custom filter that simply logs or prints a message when request is received. The idea is to give you an understand of how to write a custom filter class.

package com.codippa;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class RequestLoggerFilter implements Filter {

  private static Logger logger = LogManager.
                                  getLogger(RequestLoggerFilter.class);

  @Override
  public void doFilter(ServletRequest request, 
        ServletResponse response, FilterChain chain)
        throws IOException, ServletException {
    // print message       
    logger.info("Request received");
    // call next filter in chain
    chain.doFilter(request, response);
  }
}

Adding custom filter to Spring filter chain
Next step is to insert our custom filter in spring security chain of filters. Spring security provides different options to add a filter in its chain of filters.

A filter can be added
1. Before an inbuilt spring security filter using addFilterBefore() method.
2. After an inbuilt spring security filter using addFilterAfter() method.
3. Along with an inbuilt spring security filter using addFilterAt() method.

All of these methods are available in org.springframework.security.config.annotation.web.builders.HttpSecurity class.

To get an object of this class, create a custom spring security configuration class extending WebSecurityConfigurerAdapter and override its configure() method.
Its pretty simple and we will look at this next.
Add filter with addFilterBefore()
addFilterBefore() method accepts two arguments:
1. An object of type javax.servlet.Filter interface, which means an object of our custom filter class since it implements Filter interface.
2. Class type of one of the filters in Spring security filter chain.

This will add our filter before the specified filter of spring security.

addFilterBefore() method belongs to HttpSecurity class. To access this object, we need to create a class that extends WebSecurityConfigurerAdapter.

Example of addFilterBefore() is given below

package com.codippa;

import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
  
  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.addFilterBefore(new RequestLoggerFilter(), 
        BasicAuthenticationFilter.class);
  }
}

Here, BasicAuthenticationFilter is an inbuilt filter from spring security for processing authorization headers from incoming request.

Above code will place our filter before BasicAuthenticationFilter. This means that when we invoke doFilter() from our custom filter, it will advance to BasicAuthenticationFilter.

Add filter with addFilterAfter()
addFilterAfter() method accepts two arguments:
1. An object of type javax.servlet.Filter interface, which means an object of our custom filter class since it implements Filter interface.
2. Class type of one of the filters in Spring security filter chain.

This will add our filter after the specified filter of spring security.

addFilterAfter() method belongs to HttpSecurity class. To access this object, we need to create a class that extends WebSecurityConfigurerAdapter.

Example of addFilterAfter() is given below

package com.codippa;

import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
  
  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.addFilterAfter(new RequestLoggerFilter(), 
        BasicAuthenticationFilter.class);
  }
}

Above code will place our filter after BasicAuthenticationFilter. When we invoke doFilter() from our custom filter, it will advance to the next filter in the chain.
Add filter with addFilterAt()
addFilterAt() method accepts two arguments:
1. An object of type javax.servlet.Filter interface, which means an object of our custom filter class since it implements Filter interface.
2. Class type of one of the filters in Spring security filter chain.

This will add our filter at the same location as the specified filter of spring security.

addFilterAt() method also belongs to HttpSecurity class. To access this object, we need to create a class that extends WebSecurityConfigurerAdapter.

Example of addFilterAt() is given below

package com.codippa;

import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
  
  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.addFilterAt(new RequestLoggerFilter(), 
        BasicAuthenticationFilter.class);
  }
}

Above code will place our filter at the same location as BasicAuthenticationFilter. This does not guarantee the order of execution of these filters.
Any of the filters can be executed first out of the two.

That is all on creating a custom filter and 3 different ways to add this filter in spring security filter chain.