Spring security uses the filter chain to execute most of the security features. In this article, we will look at the Spring security filters chain. We will learn how these filters works and how they executed internally by Spring security.
Introduction
In a web application, we drive Spring security through the servlet filters. Servlet filters works by intercepting the request before it reaches to the actual resource (e.g. Spring controller). This is how filters work in a web application:
- Client sends the request for a resource (MVC controller). Application container create filter chain to process incoming request.
- Each
HttpServletRequest
pass through the filter chain based on the path of the request URI. (We can configure if we execute filter chain for all request or for specific request URI). - Filters perform the following logic on most of the web application.
- Change the
HttpServletRequest
orHttpServletResponse
before it reached to our Spring MVC controller. - Can stop the processing of the request and send a response to the client. (e.g. Servlet not allowing requests to specific URI’s).
- Change the
1. Spring Security Filters Chains
For a web application using Spring security, all incoming HttpServletRequest
goes through the spring security filters chain before it reaches to the Spring MVC controller. Before moving ahead, let’s create a Spring Security application. This will help us get a better understanding of the Spring’s FilterChain.
I am using spring boot auto configuration feature for my application, but you can build your application without Spring Boot. Most of the concept hold true for both. Create a simple controller in your application.
package com.javadevjournal.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HomeController {
@GetMapping("/home")
public String home() {
return "Welcome Home!!";
}
}
Add the following entry to the application.properties
file and run your application and hit the following URL http://localhost:8080/home
.
logging.level.org.springframework.security.web.FilterChainProxy=DEBUG
Look at the server console and you will find a similar output:
o.s.security.web.FilterChainProxy : /home at position 1 of 15 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
o.s.security.web.FilterChainProxy : /home at position 2 of 15 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
o.s.security.web.FilterChainProxy : /home at position 3 of 15 in additional filter chain; firing Filter: 'HeaderWriterFilter'
o.s.security.web.FilterChainProxy : /home at position 4 of 15 in additional filter chain; firing Filter: 'CsrfFilter'
o.s.security.web.FilterChainProxy : /home at position 5 of 15 in additional filter chain; firing Filter: 'LogoutFilter'
o.s.security.web.FilterChainProxy : /home at position 6 of 15 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
o.s.security.web.FilterChainProxy : /home at position 7 of 15 in additional filter chain; firing Filter: 'DefaultLoginPageGeneratingFilter'
o.s.security.web.FilterChainProxy : /home at position 8 of 15 in additional filter chain; firing Filter: 'DefaultLogoutPageGeneratingFilter'
o.s.security.web.FilterChainProxy : /home at position 9 of 15 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
o.s.security.web.FilterChainProxy : /home at position 10 of 15 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
o.s.security.web.FilterChainProxy : /home at position 11 of 15 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
o.s.security.web.FilterChainProxy : /home at position 12 of 15 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
o.s.security.web.FilterChainProxy : /home at position 13 of 15 in additional filter chain; firing Filter: 'SessionManagementFilter'
o.s.security.web.FilterChainProxy : /home at position 14 of 15 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
o.s.security.web.FilterChainProxy : /home at position 15 of 15 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
These filters automatically configured by Spring security and executing on each incoming Request. There are few important points to remember:
- Filters are executing in a specific order (Look at the number). The filters can change based on how we configure the modules.
- Each incoming request will go through all these filters (total 15 in our case) following a specific order.
2. How Security Filters Works
We got the basics about the Spring security and it’s workflow. Spring security performs most of its core logic using servlet filters, and it’s very important that we understand the workflow. This can help us debug or customize the security behaviour. Let’s look at the entire filters stack closely:
Above provides us a clear picture how the overall filter chain work. Let’s highlight few important points.
2.1. DelegatingFilterProxy
The DelegatingFilterProxy is a filter which works as a bridge between Servlet container’s life-cycle and Spring’s Application Context. Servlet container does not have any information about the Spring’s application context, but spring security needs security filters to execute the task..
- Since DelegatingFilterProxy is a servlet filter, the application server register it as a normal filter in the context.
- The DelegatingFilterProxy as name suggests, delegates the work to the spring bean to start the security flow.
2.2. FilterChainProxy
This filter contains all the details about the different security filters available through the security filter chain. Let’s understand few important points about the FilterChainProxy:
- The FilterChainProxy contains information about the different security filter chains and it delegates the task to the chain based on the URI’s mapping or using the RequestMatcher interface.
- It’s not executed directly but started by the DelegatingFilterProxy filter
2.3. SecurityFilterChain
We can have multiple SecurityFilterChain
configured in our application.
- Filter chain for our REST API starting with /api/v2/**.
- Filter chain for the internal communication /enterprise/**.
- Security chain for other applications /**.
- Spring security filter chain can contain multiple filters and registered with the FilterChainProxy.
- Each security filter can be configured uniquely.
The FilterChainProxy determines which SecurityFilterChain
will be invoked for an incoming request.There are several benefits of this architecture, I will highlight few advantages of this workflow:
- It provides a centralized approach to start the process. There are no multiple entry points to the security stack.
- Make it more easy to debug an application. We know where to start (FilterChainProxy is a prominent place to star).
- Security is not an optional task, it’s a central point to start the process.
- Clearing out the security context on logout is not optional and having one entry point make it easy to execute it.
Keep in mind that we invoke servlet filter based on the given URL only, but spring security filter chain provides more flexibility
- Start security filters for given URL’s
- Use the RequestMatcher to create more powerful rules to start the security filter chain (e.g. Based on the certain request header etc.)
2.4. Multiple Filter Chains:
Think about FilterChainProxy as a core module. The FilterChainProxy decides which SecurityFilterChain
should be used. It matches all incoming requests with the security filter chains and the first matched filter chain will execute.
3. Security Filters
OOTB Spring security provides several securities filters. It is typically not necessary to know every filter but keep in mind that they work in certain order or sequence. Let’s look at some important filters.
- UsernamePasswordAuthenticationFilter – Looks for the username and password in the request and tries to authenticate if found these parameters in the request.
- SecurityContextPersistenceFilter – Populates the SecurityContextHolder with information got from the configured.
- ConcurrentSessionFilter – Filter for handling concurrent session.
- DefaultLoginPageGeneratingFilter –Generates a login page for you, if you don’t explicitly disable that feature.
For a complete list, please refer to the Security Filters.
Summary
In this post, we discussed spring security filters. We saw how the security filter chain works in a web application and how the different the security filters executes. In the last part of the article, we talked about the benefits of this architecture.
A really great explanation of security filters work. Thank you!
We are happy Abhishek that it was helpful.