Today we will talk about Security Filters — one of the key mechanisms of Spring Security. You will learn what filters are, explore their architecture, and find out what filters Spring Security provides. Let's get started!
Servlet filters
First of all, let's take a look at Servlet filters on which Spring Security filters are based. With the help of these filters, we can pre-process and post-process web requests and responses. Usually, several filters are used, and they are connected by the FilterChain interface. Let's look at the following scheme to have a better idea of the concept:
The client sends the request to our server, and before the servlet got it, the request is pre-processed by the chain of filters. The filters in this case may log something, validate the input, or perform some little security tasks. Then the servlet forms the response and it is also processed by the chain of filters before the client got it. Now let's take a look at how it's implemented. Here is the main method of the Filter interface:
fun doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain) {
// Preprocessing tasks (e.g., logging, modifying request parameters)
// Pass the request through the filter chain
chain.doFilter(request, response)
// Post-processing tasks (e.g., modifying response, logging)
}First, let's take a look at the parameters of the function. ServletRequest is a special interface that represents the client's request to the server. It contains request parameters, headers, cookies, and other request information. ServletResponse is an interface representing the response that will be sent back to the client. We can set response data and a lot of parameters of it with the help of this interface. And as we mentioned before, FilterChain represents the invocation chain of a filtered request.
In this function, we can see that every filter performs its functions and invokes another resource from the chain. If something is wrong with the request (for example, for safety reasons) the processing stops and the next resource from the chain isn't invoked. So the order of filters is really important in this architecture.
Spring Security filters architecture
The logic of the Spring Security filters work is the same is pretty similar to the logic of the usual servlet ones. Moreover, Spring Security filters are integrated into the Servlet FilterChain. Let's take a look at the following scheme to understand how this architecture is implemented:
Let's break down this diagram. As you can see, it's quite similar to the one above. The Spring Security part begins with DelegatingFilterProxy. It's an implementation of the Filter interface that serves as a bridge between Servlet filters and the Spring ApplicationContext. So, DelegatingFilterProxy allows us to use Spring Beans in the filtering process. The first bean that is used is FilterChainProxy, which is wrapped in DelegatingFilterProxy. It allows us to delegate the Filter requests to the Spring Security filters. SecurityFilterChain contains several Security filters and links them. There can be several chains in the application to ensure the distinct processing of requests with different paths:
The SecurityFilterChain interface contains a function called matches. With the help of this function, FilterChainProxy checks if the request may be processed by the chain. The usual implementation of this interface, DefaultSecurityFilterChain class uses the special RequestMatcher, with the help of which we can define the strategy to match the request. The most popular case is to match with the ant-style path pattern, just like it's done in our diagram. So if a URL of the request is, for example, /edit/profile, the SecurityFilterChain 1 will be chosen, even if the third one also suits the request. The first SecurityFilterChain that matches the request is invoked, so the order of them is also important: the chains with the most URI specificated patterns of the requests have to be the first in the order if you want them to be invoked!
And what is the Security filter itself? It is the Spring Bean that implements the Filter interface. Spring Security provides us with lots of filters, and we're going to look at some of them in the next section.
Default Security filters
Spring Framework provides us with lots of default filters. Let's take a look at the most commonly used ones.
UsernamePasswordAuthenticationFilter: this filter handles the authentication process for username and password-based authentication. It is the auto-generated filter, and, for example, it processes our input when we get to the /login page.BasicAuthenticationFilter: it is responsible for processing HTTP Basic authentication. It decodes the Authorization header, extracts the username and password, and attempts to authenticate the user. It is also included in the filter chain by default.LogoutFilter: it handles the user logout process. It intercepts the logout request, clears the security context, and performs any necessary cleanup or additional actions. This filter is used by default.ExceptionTranslationFilter: it is a very important filter that handles exceptions thrown during the security process. It catches and translates authentication-related exceptions into meaningful HTTP responses, such as redirecting to a login page or returning an unauthorized status. Of course, it is used by default.AuthorizationFilter: it restricts access to the URL with the help ofAuthorizationManager. This filter is last in the Spring Security filter chain by default.RememberMeAuthenticationFilter: this filter enables "remember me" functionality. It remembers the user's authentication details (typically a token or cookie) to automatically log them in when they revisit the application. This filter is not included in the chain by default.CsrfFilter: it protects against Cross-Site Request Forgery attacks. It verifies and validates CSRF tokens in requests to ensure that they originate from trusted sources. Included by default.
Despite the fact these filters are included to the SecurityFilterChain by default, you can disable them and create your own versions of these filters instead of existing ones. Also, you can create the filters with other functionalities that aren't provided by Spring Security default filters. You will learn how to do it in later topics.
Conclusion
Now you have learned a lot about Security Filters, the key mechanism of Spring Security. In fact, all the security features of Spring applications are based on the filters: the request is safe enough if it is successfully gone through the filter chain. Now we better understand Spring Security architecture as a whole, and with a better understanding of this concept, your applications will become more secure!