This section discusses Spring Security's high-level architecture within Servlet based applications.
We build on this high-level understanding within the xref:servlet/authentication/index.adoc#servlet-authentication[Authentication], xref:servlet/authorization/index.adoc#servlet-authorization[Authorization], and xref:servlet/exploits/index.adoc#servlet-exploits[Protection Against Exploits] sections of the reference.
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 {spring-framework-reference-url}web.html#mvc-servlet[`DispatcherServlet`].
At most, one `Servlet` can handle a single `HttpServletRequest` and `HttpServletResponse`.
Spring provides a `Filter` implementation named {spring-framework-api-url}org/springframework/web/filter/DelegatingFilterProxy.html[`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`.
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.
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 <<servlet-securityfilterchain,`SecurityFilterChain`>>.
Since `FilterChainProxy` is a Bean, it is typically wrapped in a <<servlet-delegatingfilterproxy>>.
javadoc:org.springframework.security.web.SecurityFilterChain[] is used by <<servlet-filterchainproxy>> to determine which Spring Security `Filter` instances should be invoked for the current request.
The <<servlet-security-filters,Security Filters>> in `SecurityFilterChain` are typically Beans, but they are registered with `FilterChainProxy` instead of <<servlet-delegatingfilterproxy>>.
`FilterChainProxy` provides a number of advantages to registering directly with the Servlet container or <<servlet-delegatingfilterproxy>>.
First, it provides a starting point for all of Spring Security's Servlet support.
For example, it clears out the `SecurityContext` to avoid memory leaks.
It also applies Spring Security's xref:servlet/exploits/firewall.adoc#servlet-httpfirewall[`HttpFirewall`] to protect applications against certain types of attacks.
In addition, it provides more flexibility in determining when a `SecurityFilterChain` should be invoked.
In the <<servlet-multi-securityfilterchain-figure>> 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 `SecurityFilterChain~0~` pattern of `+/api/**+`, so only `SecurityFilterChain~0~` is invoked, even though it also matches on ``SecurityFilterChain~n~``.
If a URL of `/messages/` is requested, it does not match on the `SecurityFilterChain~0~` pattern of `+/api/**+`, so `FilterChainProxy` continues trying each `SecurityFilterChain`.
Assuming that no other `SecurityFilterChain` instances match, `SecurityFilterChain~n~` is invoked.
// FIXME: add link to pattern matching
Notice that `SecurityFilterChain~0~` has only three security `Filter` instances configured.
xref:servlet/exploits/index.adoc[exploit protection], xref:servlet/authentication/index.adoc[authentication], xref:servlet/authorization/index.adoc[authorization], 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.
However, there are times that it is beneficial to know the ordering, if you want to know them, you can check the {gh-url}/config/src/main/java/org/springframework/security/config/annotation/web/builders/FilterOrderRegistration.java[`FilterOrderRegistration` code].
These security filters are most often declared using an javadoc:org.springframework.security.config.annotation.web.builders.HttpSecurity[`HttpSecurity`] instance.
The list of filters is printed at DEBUG level on the application startup, so you can see something like the following on the console output for example:
Most of the time, the default <<servlet-security-filters>> are enough to provide security to your application.
However, there might be times that you want to add a custom `Filter` to the <<servlet-securityfilterchain>>.
javadoc:org.springframework.security.config.annotation.web.builders.HttpSecurity[] comes with three methods for adding filters:
* `#addFilterBefore(Filter, Class<?>)` adds your filter before another filter
* `#addFilterAfter(Filter, Class<?>)` adds your filter after another filter
* `#addFilterAt(Filter, Class<?>)` replaces another filter with your filter
==== Adding a Custom Filter
If you are creating a filter of your own, you will need to determine its location in the filter chain.
Please take a look at the following key events that occur in the filter chain:
1. xref:servlet/authentication/architecture.adoc#servlet-authentication-securitycontextholder[`SecurityContext`] is loaded from the session
2. Request is protected from common exploits; xref:features/exploits/headers.adoc[secure headers], xref:servlet/integrations/cors.adoc[CORS], xref:servlet/exploits/csrf.adoc[CSRF]
3. Request is xref:servlet/authentication/architecture.adoc[authenticated]
4. Request is xref:servlet/authorization/architecture.adoc[authorized]
Consider which events you need to have happened in order to locate your filter.
The following is a rule of thumb:
[cols="1,1,1"]
|===
| If your filter is a(n) | Then place it after | As these events have already occurred
throw new AccessDeniedException("Access denied"); <4>
}
}
----
The sample code above does the following:
<1> Get the tenant id from the request header.
<2> Check if the current user has access to the tenant id.
<3> If the user has access, then invoke the rest of the filters in the chain.
<4> If the user does not have access, then throw an `AccessDeniedException`.
[TIP]
====
Instead of implementing `Filter`, you can extend from {spring-framework-api-url}org/springframework/web/filter/OncePerRequestFilter.html[OncePerRequestFilter] which is a base class for filters that are only invoked once per request and provides a `doFilterInternal` method with the `HttpServletRequest` and `HttpServletResponse` parameters.
Now, you need to add the filter to the <<servlet-securityfilterchain>>.
The previous description already gives us a clue on where to add the filter, since we need to know the current user, we need to add it after the authentication filters.
Based on the rule of thumb, add it after xref:servlet/authentication/anonymous.adoc[ `AnonymousAuthenticationFilter`], the last authentication filter in the chain, like so:
By adding the filter after the xref:servlet/authentication/anonymous.adoc[`AnonymousAuthenticationFilter`] we are making sure that the `TenantFilter` is invoked after the authentication filters.
When you declare a `Filter` as a Spring bean, either by annotating it with `@Component` or by declaring it as a bean in your configuration, Spring Boot automatically {spring-boot-reference-url}reference/web/servlet.html#web.servlet.embedded-container.servlets-filters-listeners.beans[registers it with the embedded container].
Because of that, filters are often not Spring beans.
However, if your filter needs to be a Spring bean (to take advantage of dependency injection, for example) you can tell Spring Boot to not register it with the container by declaring a `FilterRegistrationBean` bean and setting its `enabled` property to `false`:
In this case, remove the call to `httpBasic` since you are constructing `BasicAuthenticationFilter` yourself.
[TIP]
====
In the event that you are unable to reconfigure `HttpSecurity` to not add a certain filter, you can typically disable the Spring Security filter by calling its DSL's `disable` method like so:
The javadoc:org.springframework.security.web.access.ExceptionTranslationFilter[] allows translation of javadoc:org.springframework.security.access.AccessDeniedException[] and javadoc:org.springframework.security.core.AuthenticationException[] into HTTP responses.
* image:{icondir}/number_1.png[] First, the `ExceptionTranslationFilter` invokes `FilterChain.doFilter(request, response)` to invoke the rest of the application.
* image:{icondir}/number_2.png[] If the user is not authenticated or it is an `AuthenticationException`, then __Start Authentication__.
<1> As described in <<servlet-filters-review>>, invoking `FilterChain.doFilter(request, response)` is the equivalent of invoking the rest of the application.
This means that if another part of the application, (xref:servlet/authorization/authorize-http-requests.adoc[`AuthorizationFilter`] or method security) throws an `AuthenticationException` or `AccessDeniedException` it is caught and handled here.
As illustrated in <<servlet-exceptiontranslationfilter>>, when a request has no authentication and is for a resource that requires authentication, there is a need to save the request for the authenticated resource to re-request after authentication is successful.
In Spring Security this is done by saving the `HttpServletRequest` using a <<requestcache,`RequestCache`>> implementation.
The <<requestcacheawarefilter,`RequestCacheAwareFilter`>> uses the `RequestCache` to get the saved `HttpServletRequest` after the user authenticates, while the `ExceptionTranslationFilter` uses the `RequestCache` to save the `HttpServletRequest` after it detects `AuthenticationException`, before redirecting the user to the login endpoint.
The code below demonstrates how to customize the `RequestCache` implementation that is used to check the `HttpSession` for a saved request if the parameter named `continue` is present.
There are a number of reasons you may want to not store the user's unauthenticated request in the session.
You may want to offload that storage onto the user's browser or store it in a database.
Or you may want to shut off this feature since you always want to redirect the user to the home page instead of the page they tried to visit before login.
The javadoc:org.springframework.security.web.savedrequest.RequestCacheAwareFilter[] uses the <<requestcache,`RequestCache`>> to replay the original request.
Spring Security provides comprehensive logging of all security related events at the DEBUG and TRACE level.
This can be very useful when debugging your application because for security measures Spring Security does not add any detail of why a request has been rejected to the response body.
If you come across a 401 or 403 error, it is very likely that you will find a log message that will help you understand what is going on.
Let's consider an example where a user tries to make a `POST` request to a resource that has xref:servlet/exploits/csrf.adoc[CSRF protection] enabled without the CSRF token.
With no logs, the user will see a 403 error with no explanation of why the request was rejected.
However, if you enable logging for Spring Security, you will see a log message like this:
[source,text]
----
2023-06-14T09:44:25.797-03:00 DEBUG 76975 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : Securing POST /hello
2023-06-14T09:44:25.814-03:00 DEBUG 76975 --- [nio-8080-exec-1] o.s.security.web.csrf.CsrfFilter : Invalid CSRF token found for http://localhost:8080/hello
2023-06-14T09:44:25.814-03:00 DEBUG 76975 --- [nio-8080-exec-1] o.s.s.w.access.AccessDeniedHandlerImpl : Responding with 403 status code
2023-06-14T09:44:25.814-03:00 TRACE 76975 --- [nio-8080-exec-1] o.s.s.w.header.writers.HstsHeaderWriter : Not injecting HSTS header since it did not match request to [Is Secure]
----
It becomes clear that the CSRF token is missing and that is why the request is being denied.
To configure your application to log all the security events, you can add the following to your application: