Spring security - Architecture

Table of Contents

https://docs.spring.io/spring-security/reference/servlet/architecture.html

Spring Security’s Servlet support is based on Servlet Filters. Spring Interceptors vs Servlet Filters

Key components

  1. DelegatingFilterProxy - https://docs.spring.io/spring-security/reference/servlet/architecture.html#servlet-delegatingfilterproxy

    https://docs.spring.io/spring-framework/docs/6.1.2/javadoc-api/org/springframework/web/filter/DelegatingFilterProxy.html

    Spring provides a Filter implementation named DelegatingFilterProxy that allows bridging between the Servlet container’s lifecycle and Spring’s ApplicationContext. The Servlet container allows registering Filter instances by using its own standards, but it is not aware of Spring-defined Beans. You can register DelegatingFilterProxy through the standard Servlet container mechanisms but delegate all the work to a Spring Bean that implements Filter.

    DelegatingFilterProxy looks up Bean Filter from the ApplicationContext and then invokes Bean Filter. The following listing shows pseudo code of DelegatingFilterProxy.

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
         Filter delegate = getFilterBean(someBeanName);
         delegate.doFilter(request, response);
    }
    
    1. Filter delegate = getFilterBean(someBeanName); - Lazily get Filter that was registered as a Spring Bean.

    2. delegate.doFilter(request, response); - Delegate work to the Spring Bean

      Another benefit of DelegatingFilterProxy is that it allows delaying looking up Filter bean instances. This is important because the container needs to register the Filter instances before the container can start up. However, Spring typically uses a ContextLoaderListener to load the Spring Beans, which is not done until after the Filter instances need to be registered.

  2. FilterChainProxy - https://docs.spring.io/spring-security/reference/servlet/architecture.html#servlet-filterchainproxy

    Spring Security’s Servlet support is contained within FilterChainProxy. FilterChainProxy is a special Filter provided by Spring Security that allows delegating to many Filter instances through SecurityFilterChain. Since FilterChainProxy is a Bean, it is typically wrapped in a DelegatingFilterProxy.

  3. SecurityFilterChain - https://docs.spring.io/spring-security/reference/servlet/architecture.html#servlet-securityfilterchain

    SecurityFilterChain is used by FilterChainProxy to determine which Spring Security Filter instances should be invoked for the current request.

    The Security Filters in SecurityFilterChain are typically Beans, but they are registered with FilterChainProxy instead of DelegatingFilterProxy. FilterChainProxy provides a number of advantages to registering directly with the Servlet container or DelegatingFilterProxy. First, it provides a starting point for all of Spring Security’s Servlet support. For that reason, if you try to troubleshoot Spring Security’s Servlet support, adding a debug point in FilterChainProxy is a great place to start.

  4. Security Filters - https://docs.spring.io/spring-security/reference/servlet/architecture.html#servlet-security-filters

    The Security Filters are inserted into the FilterChainProxy with the SecurityFilterChain API. Those filters can be used for a number of different purposes, like authentication, authorization, exploit protection, and more. The filters are executed in a specific order to guarantee that they are invoked at the right time, for example, the Filter that performs authentication should be invoked before the Filter that performs authorization. It is typically not necessary to know the ordering of Spring Security’s Filters. However, there are times that it is beneficial to know the ordering, if you want to know them, you can check the FilterOrderRegistration code.

    1. Adding a Custom Filter to the Filter Chain
      @Bean
      SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
          http
              // ...
              .addFilterBefore(new TenantFilter(), AuthorizationFilter.class);
          return http.build();
      }
      

    https://github.com/spring-projects/spring-security/blob/6.2.1/config/src/main/java/org/springframework/security/config/annotation/web/builders/FilterOrderRegistration.java

  5. Handling Security Exceptions - https://docs.spring.io/spring-security/reference/servlet/architecture.html#servlet-exceptiontranslationfilter

  6. Saving Requests Between Authentication - https://docs.spring.io/spring-security/reference/servlet/architecture.html#savedrequests

  7. Logging - https://docs.spring.io/spring-security/reference/servlet/architecture.html#servlet-logging


Spring Security maintains a SecurityFilterChain internally where filters we can be added/removed from the configuration depending on the services required. Based on the services requirements, we can add or replace filters, since each filter has a specific responsibility in the filter chain.

  1. SecurityContextIntegrationFilter Responsible to establish SecurityContext and maintaining it between HTTP requests.
  2. LogoutFilter Clears the SecurityContextHolder whenever we logout.
  3. UsernamePasswordAuthenticationFilter This filter is responsible to Authenticate to SecurityContext whenever we require login.
  4. ExceptionTranslationFilter Responsible for converting SpringSecurity exceptions to HTTP responses.
  5. FilterSecurityInterceptor This filter performs security handling of HTTP resources through filter implementation. This filter also allows requests based on authorities.

Links to this note