Spring Security — The Security Filter Chain

Kasun Dissanayake
7 min readApr 4, 2023

--

In this article, we are going to learn about the Spring Scerity Filter Chain. Underneath of code of Spring, Security is going to be using a security chain. Spring Security’s web infrastructure is based entirely on standard servlet filters. It doesn’t use servlets or any other servlet-based frameworks (such as Spring MVC) internally, so it has no strong links to any particular web technology. It deals in HttpServletRequests and HttpServletResponses and doesn't care whether the requests come from a browser, a web service client, an HttpInvoker or an AJAX application.

Spring Security maintains a filter chain internally where each of the filters has a particular responsibility and filters are added or removed from the configuration depending on which services are required. The ordering of the filters is important as there are dependencies between them. If you have been using namespace configuration, then the filters are automatically configured for you and you don’t have to define any Spring beans explicitly but there may be times when you want full control over the security filter chain, either because you are using features which aren’t supported in the namespace, or you are using your customized versions of classes.

First of all, look at this diagram given below we first send an HTTP request to our server what is going to happen is it will go through a set of Security Filters. They are just chains of filters that you use to do or perform certain actions on Spring Security.

It is almost like a Middleware and it has the name of FilterChain because of the chain of responsibility pattern. The HTTP request going to pass through it and the response also passes through the filters based on the way that it is going. Then finally the request is routed to the controllers by this servlet. Servlet takes the HTTP request and does some kind of action to it depending on the Java code.

The name chain suggests that you have a sequence of filters, with each filter doing some processing and then passing on to the next in sequence, so each object has a chain member to point to the next filter in the sequence, which gets called after the filter has performed its processing. The last in the sequence will then probably have null as the chain value or it knows on its own that it is the last one in the sequence.

This process internally invokes doFilter of the next filter in the filter chain, and, when the chain is over, it invokes the target servlet. All filters are chained (in the order of their definition in web.xml). The chain.doFilter() proceeds to the next element in the chain. The last element of the chain is the target resource/servlet.

What’s happening here is Spring Scerity provides a deligating Fiter Proxy and we called it Bean Filter. It allows us to just look at the request, so the servlet is going to get a request and response. Then these filters will be applied to those requests. This is a very important concept of architecture. These filters get applied and you can have different security filter chains that allow you to have one endpoint that’s ominous and another one that requires authentication. Some could just say, “Okay, well just using a remember me cookie is just fine.” So it gives you a lot of flexibility in your architecture as to how you work with Spring Security. So Spring Security has been around for a long time. It's very mature, so you can do a lot of capabilities with it as to how you configure it. So the key takeaway I want you to have from this article is that Spring Security is setting up a filter chain and there os multiple filter chains based on your configurations. Those filters get applied to the request and response ahead of or behind the Soring Security Dispatcher Servlet.

Now, let’s look at the core components that take part in the filter chain:

  1. DelegatingFilterProxy It is a servlet filter provided by Spring that acts as a bridge between the Servlet container and the Spring Application Context. The DelegatingFilterProxy class is responsible for wiring any class that implements javax.servlet.Filter into the filter chain.
  2. FilterChainProxy Spring security internally creates a FilterChainProxy bean named springSecurityFilterChain wrapped in DelegatingFilterProxy. The FilterChainProxy is a filter that chains multiple filters based on the security configuration. Thus, the DelegatingFilterProxy delegates request the FilterChainProxy which determines the filters to be invoked.
  3. SecurityFilterChain: The security filters in the SecurityFilterChain are beans registered with FilterChainProxy. An application can have multiple SecurityFilterChain. FilterChainProxy uses the RequestMatcher interface on HttpServletRequest to determine which SecurityFilterChain needs to be called

Let’s implement this logic to get a perfect idea of what is a Security Filter Chain. Now create a folder called security in your project and create a class called SecurityConfig.

This is the class we use to add our filter chain. Now add the annotation @Configuration to let the spring boot this is a configuration class and this needs to be added to the Bean Context. In the previous versions, we have used WebSecurityConfigurerAdapter to implement this and now WebSecurityConfigurerAdapter is deprecated. In Spring Security 5.7.0-M2 they deprecated the WebSecurityConfigurerAdapter, as they encourage users to move towards a component-based security configuration. To assist with the transition to this new style of configuration, they have compiled a list of common use cases and suggested alternatives going forward. In the examples below we follow best practices by using the Spring Security lambda DSL and the method HttpSecurity#authorizeHttpRequests to define our authorization rules. If you are new to the lambda DSL you can read about it in this blog post. If you would like to learn more about why we chose to use HttpSecurity#authorizeHttpRequests you can check out the reference documentation.

Configuring HttpSecurity

In Spring Security 5.4 they introduced the ability to configure HttpSecurity by creating a SecurityFilterChain bean.

Below is an example configuration using the WebSecurityConfigurerAdapter that secures all endpoints with HTTP Basic:

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic();
}

}

Going forward, the recommended way of doing this is to register a SecurityFilterChain bean:

@Configuration
public class SecurityConfig {

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic();
return http.build();
}
}

You can add any security chain expressions here like.

  1. org.springframework.security.web.csrf.CsrfFilter : This filter applies for CSRF protection by default to all REST endpoints.
  2. org.springframework.security.web.authentication.logout.LogoutFilter : This filter gets called when the user logs out of the application. The default registered instances LogoutHandler are called that are responsible for invalidating the session and clearing the SecurityContext. Next, the default implementation of LogoutSuccessHandler redirects the user to a new page (/login?logout).
  3. org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter : Validates the username and password for the URL (/login) with the default credentials provided at startup.
  4. org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter : Generates the default login page html at /login
  5. org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter : Generates the default logout page html at /login?logout
  6. org.springframework.security.web.authentication.www.BasicAuthenticationFilter : This filter is responsible for processing any request that has an HTTP request header of Authorization, Basic Authentication scheme, Base64 encoded username-password. On successful authentication, the Authentication object will be placed in the SecurityContextHolder.
  7. org.springframework.security.web.authentication.AnonymousAuthenticationFilter : If no Authentication the object is found in the SecurityContext, it creates one with the principal anonymousUser and role ROLE_ANONYMOUS.
  8. org.springframework.security.web.access.ExceptionTranslationFilter : Handles AccessDeniedException and AuthenticationException thrown within the filter chain. For AuthenticationException instance of AuthenticationEntryPoint are required to handle responses. For, this filter will delegate to AccessDeniedHandler whose default implementation is AccessDeniedHandlerImpl.
  9. org.springframework.security.web.access.intercept.FilterSecurityInterceptor : This filter is responsible for authorizing every request that passes through the filter chain before the request hits the controller.

Additional Notes on Spring Security Chain

  • The default fallback filter chain in a Spring Boot application has a request matcher /**, meaning it will apply to all requests.
  • The default filter chain has a predefined @Order SecurityProperties.BASIC_AUTH_ORDER.
  • We can exclude this complete filter chain by setting security.basic.enabled=false.
  • We can define the ordering of multiple filter chains. For instance, to call a custom filter chain before the default one, we need to set a lower @Order. Example @Order(SecurityProperties.BASIC_AUTH_ORDER - 10).
  • We can plugin a custom filter within the existing filter chain (to be called at all times or for specific URL patterns) using the FilterRegistrationBean or by extending OncePerRequestFilter.
  • For the defined custom filter, if no @Order is specified, it is the last in the security chain. (Has the default order LOWEST_PRECEDENCE.)
  • We can also use methods addFilterAfter(), addFilterAt() and addFilterBefore() to have more control over the ordering of our defined custom filter.

In this article, we looked at the basic concept that applies to spring security. As we have seen, spring provides a lot of flexibility and allows us to customize security for complex applications. See you in another article.

Thank You!

--

--

Kasun Dissanayake

Senior Software Engineer at IFS R & D International || Former Software Engineer at Pearson Lanka || Former Associate Software Engineer at hSenid Mobile