This version is still in development and is not considered stable yet. For the latest stable version, please use Spring Security 6.0.1! |
Architecture
This section discusses Spring Security’s high-level architecture within Servlet based applications. We build on this high-level understanding within the Authentication, Authorization, and Protection Against Exploits sections of the reference.
A Review of Filters
Spring Security’s Servlet support is based on Servlet Filters, so it is helpful to look at the role of Filters generally first. The following image shows the typical layering of the handlers for a single HTTP request.

The client sends a request to the application, and the container creates a FilterChain
, which contains the Filter
instances and Servlet
that should process the HttpServletRequest
, based on the path of the request URI.
In a Spring MVC application, the Servlet
is an instance of DispatcherServlet
.
At most, one Servlet
can handle a single HttpServletRequest
and HttpServletResponse
.
However, more than one Filter
can be used to:
-
Prevent downstream
Filter
instances or theServlet
from being invoked. In this case, theFilter
typically writes theHttpServletResponse
. -
Modify the
HttpServletRequest
orHttpServletResponse
used by the downstreamFilter
instances and theServlet
.
The power of the Filter
comes from the FilterChain
that is passed into it.
FilterChain
Usage Example-
Java
-
Kotlin
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
// do something before the rest of the application
chain.doFilter(request, response); // invoke the rest of the application
// do something after the rest of the application
}
fun doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain) {
// do something before the rest of the application
chain.doFilter(request, response) // invoke the rest of the application
// do something after the rest of the application
}
Since a Filter
impacts only downstream Filter
instances and the Servlet
, the order in which each Filter
is invoked is extremely important.
DelegatingFilterProxy
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
.
Here is a picture of how DelegatingFilterProxy
fits into the Filter
instances and the FilterChain
.

DelegatingFilterProxy
looks up Bean Filter0 from the ApplicationContext
and then invokes Bean Filter0.
The following listing shows pseudo code of DelegatingFilterProxy
:
DelegatingFilterProxy
Pseudo Code-
Java
-
Kotlin
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
// Lazily get Filter that was registered as a Spring Bean
// For the example in DelegatingFilterProxy delegate
is an instance of Bean Filter0
Filter delegate = getFilterBean(someBeanName);
// delegate work to the Spring Bean
delegate.doFilter(request, response);
}
fun doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain) {
// Lazily get Filter that was registered as a Spring Bean
// For the example in DelegatingFilterProxy delegate
is an instance of Bean Filter0
val delegate: Filter = getFilterBean(someBeanName)
// delegate work to the Spring Bean
delegate.doFilter(request, response)
}
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.
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.
The following image shows the role of FilterChainProxy
.

SecurityFilterChain
SecurityFilterChain
is used by FilterChainProxy to determine which Spring Security Filter
instances should be invoked for the current request.
The following image shows the role of SecurityFilterChain
.

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.
Second, since FilterChainProxy
is central to Spring Security usage, it can perform tasks that are not viewed as optional.
For example, it clears out the SecurityContext
to avoid memory leaks.
It also applies Spring Security’s HttpFirewall
to protect applications against certain types of attacks.
In addition, it provides more flexibility in determining when a SecurityFilterChain
should be invoked.
In a Servlet container, Filter
instances are invoked based upon the URL alone.
However, FilterChainProxy
can determine invocation based upon anything in the HttpServletRequest
by using the RequestMatcher
interface.
The following image shows multiple SecurityFilterChain
instances:

In the Multiple SecurityFilterChain figure, FilterChainProxy
decides which SecurityFilterChain
should be used.
Only the first SecurityFilterChain
that matches is invoked.
If a URL of /api/messages/
is requested, it first matches on the SecurityFilterChain0
pattern of /api/**
, so only SecurityFilterChain0
is invoked, even though it also matches on SecurityFilterChainn
.
If a URL of /messages/
is requested, it does not match on the SecurityFilterChain0
pattern of /api/**
, so FilterChainProxy
continues trying each SecurityFilterChain
.
Assuming that no other SecurityFilterChain
instances match, SecurityFilterChainn
is invoked.
Notice that SecurityFilterChain0
has only three security Filter
instances configured.
However, SecurityFilterChainn
has four security Filter
instanes configured.
It is important to note that each SecurityFilterChain
can be unique and can be configured in isolation.
In fact, a SecurityFilterChain
might have zero security Filter
instances if the application wants Spring Security to ignore certain requests.
Security Filters
The Security Filters are inserted into the FilterChainProxy with the SecurityFilterChain API.
The order of Filter
instances matters.
It is typically not necessary to know the ordering of Spring Security’s Filter
instances.
However, there are times that it is beneficial to know the ordering.
The following is a comprehensive list of Spring Security Filter ordering:
-
ChannelProcessingFilter
-
WebAsyncManagerIntegrationFilter
-
SecurityContextPersistenceFilter
-
HeaderWriterFilter
-
CorsFilter
-
CsrfFilter
-
LogoutFilter
-
OAuth2AuthorizationRequestRedirectFilter
-
Saml2WebSsoAuthenticationRequestFilter
-
X509AuthenticationFilter
-
AbstractPreAuthenticatedProcessingFilter
-
CasAuthenticationFilter
-
OAuth2LoginAuthenticationFilter
-
Saml2WebSsoAuthenticationFilter
-
DefaultLoginPageGeneratingFilter
-
DefaultLogoutPageGeneratingFilter
-
ConcurrentSessionFilter
-
BearerTokenAuthenticationFilter
-
RequestCacheAwareFilter
-
SecurityContextHolderAwareRequestFilter
-
JaasApiIntegrationFilter
-
RememberMeAuthenticationFilter
-
AnonymousAuthenticationFilter
-
OAuth2AuthorizationCodeGrantFilter
-
SessionManagementFilter
-
SwitchUserFilter
Handling Security Exceptions
The ExceptionTranslationFilter
allows translation of AccessDeniedException
and AuthenticationException
into HTTP responses.
ExceptionTranslationFilter
is inserted into the FilterChainProxy as one of the Security Filters.
The following image shows the relationship of ExceptionTranslationFilter
to other components:

-
First, the
ExceptionTranslationFilter
invokesFilterChain.doFilter(request, response)
to invoke the rest of the application. -
If the user is not authenticated or it is an
AuthenticationException
, then Start Authentication.-
The SecurityContextHolder is cleared out.
-
The
HttpServletRequest
is saved in theRequestCache
. When the user successfully authenticates, theRequestCache
is used to replay the original request. -
The
AuthenticationEntryPoint
is used to request credentials from the client. For example, it might redirect to a log in page or send aWWW-Authenticate
header.
-
-
Otherwise, if it is an
AccessDeniedException
, then Access Denied. TheAccessDeniedHandler
is invoked to handle access denied.
If the application does not throw an |
The pseudocode for ExceptionTranslationFilter
looks something like this:
try {
filterChain.doFilter(request, response); (1)
} catch (AccessDeniedException | AuthenticationException ex) {
if (!authenticated || ex instanceof AuthenticationException) {
startAuthentication(); (2)
} else {
accessDenied(); (3)
}
}
1 | As described in A Review of Filters, invoking FilterChain.doFilter(request, response) is the equivalent of invoking the rest of the application.
This means that if another part of the application, (FilterSecurityInterceptor or method security) throws an AuthenticationException or AccessDeniedException it is caught and handled here. |
2 | If the user is not authenticated or it is an AuthenticationException , Start Authentication. |
3 | Otherwise, Access Denied |