diff --git a/docs/manual/src/docs/asciidoc/_includes/servlet/architecture/index.adoc b/docs/manual/src/docs/asciidoc/_includes/servlet/architecture/index.adoc index 47590edfe7..4a9b4a4cb5 100644 --- a/docs/manual/src/docs/asciidoc/_includes/servlet/architecture/index.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/servlet/architecture/index.adoc @@ -1,8 +1,170 @@ -[[overall-architecture]] +[[servlet-architecture]] = Architecture and Implementation -Once you are familiar with setting up and running some namespace-configuration based applications, you may wish to develop more of an understanding of how the framework actually works behind the namespace facade. -Like most software, Spring Security has certain central interfaces, classes and conceptual abstractions that are commonly used throughout the framework. -In this part of the reference guide we will look at some of these and see how they work together to support authentication and access-control within Spring Security. +:figures: images/servlet/architecture + +This section discusses Spring Security's high level architecture within Servlet based applications. +We build on this high level understanding within each section of the reference. +// FIXME: Add links to other sections of architecture + +[[servlet-filters-review]] +== A Review of ``Filter``s + +Spring Security's Servlet support is based on Servlet ``Filter``s, so it is helpful to look at the role of ``Filter``s generally first. +The picture below shows the typical layering of the handlers for a single HTTP request. + +.FilterChain +[[servlet-filterchain-figure]] +image::{figures}/filterchain.svg[] + +The client sends a request to the application, and the container creates a `FilterChain` which contains the ``Filter``s and `Servlet` that should process the `HttpServletRequest` based on the path of the request URI. +At most one `Servlet` can handle a single `HttpServletRequest` and `HttpServletResponse`. +However, more than one `Filter` can be used to: + +* Prevent downstream ``Filter``s or the `Servlet` from being invoked. +In this instance the `Filter` will typically write the `HttpServletResponse`. +* Modify the `HttpServletRequest` or `HttpServletResponse` used by the downstream ``Filter``s and `Servlet` + +The power of the `Filter` comes from the `FilterChain` that is passed into it. + +.`FilterChain` Usage Example +==== +[source,java] +---- +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 +} +---- +==== + +Since a `Filter` only impacts downstream ``Filter``s and the `Servlet`, the order each `Filter` is invoked is extremely important. + +[[servlet-delegatingfilterproxy]] +== 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``s using its own standards, but it is not aware of Spring defined Beans. +`DelegatingFilterProxy` can be registered via 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 <>. + +.DelegatingFilterProxy +[[servlet-delegatingfilterproxy-figure]] +image::{figures}/delegatingfilterproxy.svg[] + +`DelegatingFilterProxy` looks up __Bean Filter~0~__ from the `ApplicationContext` and then invokes __Bean Filter~0~__. +The pseudo code of `DelegatingFilterProxy` can be seen below. + +.`DelegatingFilterProxy` Pseudo Code +==== +[source,java,subs="+quotes,+macros"] +---- +public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) { + // Lazily get Filter that was registered as a Spring Bean + // For the example in <> `delegate` is an instance of __Bean Filter~0~__ + Filter delegate = getFilterBean(someBeanName); + // delegate work to the Spring Bean + delegate.doFilter(request, response); +} +---- +==== + +Another benefit of `DelegatingFilterProxy` is that it allows delaying looking `Filter` bean instances. +This is important because the container needs to register the `Filter` instances before the container can startup. +However, Spring typically uses a `ContextLoaderListener` to load the Spring Beans which will not be done until after the `Filter` instances need to be registered. + +[[servlet-filterchainproxy]] +== 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 the `SecurityFilterChain` API. +// FIXME: link to SecurityFilterChain +Since `FilterChainProxy` is a Bean, it is typically wrapped in a <>. + +.FilterChainProxy +[[servlet-filterchainproxy-figure]] +image::{figures}/filterchainproxy.svg[] + +The <> in `SecurityFilterChain` are typically Beans, but they are registered with `FilterChainProxy` instead of <>. +`FilterChainProxy` provides a number of advantages to registering directly with the Servlet container or <>. +First, it provides a starting point for all of Spring Security's Servlet support. +For that reason, if you are attempting 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. +// FIXME: Add a link to SecurityContext +For example, it clears out the `SecurityContext` to avoid memory leaks. +// FIXME: Add a link to HttpFirewall +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. +// FIXME: Add link to SecurityFitlerChain +In a Servlet container, ``Filter``s are invoked based upon the URL alone. +// FIXME: Link to RequestMatcher +However, `FilterChainProxy` can determine invocation based upon anything in the `HttpServletRequest` by leveraging the `RequestMatcher` interface. + +In fact, `FilterChainProxy` can be used to determine which `SecurityFilterChain` should be used. +This allows providing a totally separate configuration for different _slices_ if your application. + +.Multiple SecurityFilterChain +[[servlet-multi-securityfilterchain-figure]] +image::{figures}/multi-securityfilterchain.svg[] + +In the <> Figure `FilterChainProxy` decides which `SecurityFilterChain` should be used. +Only the first `SecurityFilterChain` that matches will be invoked. +If a URL of `/api/messages/` is requested, it will first match on ``SecurityFilterChain~0~``'s pattern of `+/api/**+`, so only `SecurityFilterChain~0~` will be invoked even though it also matches on ``SecurityFilterChain~n~``. +If a URL of `/messages/` is requested, it will not match on ``SecurityFilterChain~0~``'s pattern of `+/api/**+`, so `FilterChainProxy` will continue trying each `SecurityFilterChain`. +Assuming that no other, `SecurityFilterChain` instances match `SecurityFilterChain~n~` will be invoked. +// FIXME add link to pattern matching + +Notice that `SecurityFilterChain~0~` has only three security ``Filter``s instances configured. +However, `SecurityFilterChain~n~` has four security ``Filter``s configured. +It is important to note that each `SecurityFilterChain` can be unique and configured in isolation. +In fact, a `SecurityFilterChain` might have zero security ``Filter``s if the application wants Spring Security to ignore certain requests. +// FIXME: add link to configuring multiple `SecurityFilterChain` instances + +[[servlet-security-filters]] +== Security Filters + +The <>s matters. +It is typically not necessary to know the ordering of Spring Security's ``Filter``s. +However, there are times that it is beneficial to know the ordering + +Below is a comprehensive list of Spring Security Filter ordering: + +* ChannelProcessingFilter +* ConcurrentSessionFilter +* WebAsyncManagerIntegrationFilter +* SecurityContextPersistenceFilter +* HeaderWriterFilter +* CorsFilter +* CsrfFilter +* LogoutFilter +* OAuth2AuthorizationRequestRedirectFilter +* Saml2WebSsoAuthenticationRequestFilter +* X509AuthenticationFilter +* AbstractPreAuthenticatedProcessingFilter +* CasAuthenticationFilter +* OAuth2LoginAuthenticationFilter +* Saml2WebSsoAuthenticationFilter +* UsernamePasswordAuthenticationFilter +* ConcurrentSessionFilter +* OpenIDAuthenticationFilter +* DefaultLoginPageGeneratingFilter +* DefaultLogoutPageGeneratingFilter +* DigestAuthenticationFilter +* BearerTokenAuthenticationFilter +* BasicAuthenticationFilter +* RequestCacheAwareFilter +* SecurityContextHolderAwareRequestFilter +* JaasApiIntegrationFilter +* RememberMeAuthenticationFilter +* AnonymousAuthenticationFilter +* OAuth2AuthorizationCodeGrantFilter +* SessionManagementFilter +* ExceptionTranslationFilter +* FilterSecurityInterceptor +* SwitchUserFilter include::technical-overview.adoc[] diff --git a/docs/manual/src/docs/asciidoc/images/servlet/architecture/delegatingfilterproxy.odg b/docs/manual/src/docs/asciidoc/images/servlet/architecture/delegatingfilterproxy.odg new file mode 100644 index 0000000000..8b0ea34296 Binary files /dev/null and b/docs/manual/src/docs/asciidoc/images/servlet/architecture/delegatingfilterproxy.odg differ diff --git a/docs/manual/src/docs/asciidoc/images/servlet/architecture/delegatingfilterproxy.svg b/docs/manual/src/docs/asciidoc/images/servlet/architecture/delegatingfilterproxy.svg new file mode 100644 index 0000000000..8a604f0288 --- /dev/null +++ b/docs/manual/src/docs/asciidoc/images/servlet/architecture/delegatingfilterproxy.svg @@ -0,0 +1,512 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + DelegatingFilterProxy + + + + DelegatingFilterProxy + + + + + + + + + + + + + + + + + + + + + + + + Client + + + + Client + + + + + + + + + + + + + + + + + + + + + + + + Servlet + + + + Servlet + + + + + + + + + + + + + + + + + + + + + + + + Filter0 + + + + Filter0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Filter2 + + + + Filter2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + FilterChain + + + + + + + + Bean Filter0 + + + + + + + + \ No newline at end of file diff --git a/docs/manual/src/docs/asciidoc/images/servlet/architecture/filterchain.odg b/docs/manual/src/docs/asciidoc/images/servlet/architecture/filterchain.odg new file mode 100644 index 0000000000..10b599eb52 Binary files /dev/null and b/docs/manual/src/docs/asciidoc/images/servlet/architecture/filterchain.odg differ diff --git a/docs/manual/src/docs/asciidoc/images/servlet/architecture/filterchain.svg b/docs/manual/src/docs/asciidoc/images/servlet/architecture/filterchain.svg new file mode 100644 index 0000000000..1bf2ec997f --- /dev/null +++ b/docs/manual/src/docs/asciidoc/images/servlet/architecture/filterchain.svg @@ -0,0 +1,481 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Filter1 + + + + Filter1 + + + + + + + + + + + + + + + + + + + + + + + + Client + + + + Client + + + + + + + + + + + + + + + + + + + + + + + + Servlet + + + + Servlet + + + + + + + + + + + + + + + + + + + + + + + + Filter0 + + + + Filter0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Filter2 + + + + Filter2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + FilterChain + + + + + + + + \ No newline at end of file diff --git a/docs/manual/src/docs/asciidoc/images/servlet/architecture/filterchainproxy.odg b/docs/manual/src/docs/asciidoc/images/servlet/architecture/filterchainproxy.odg new file mode 100644 index 0000000000..956b74ec19 Binary files /dev/null and b/docs/manual/src/docs/asciidoc/images/servlet/architecture/filterchainproxy.odg differ diff --git a/docs/manual/src/docs/asciidoc/images/servlet/architecture/filterchainproxy.svg b/docs/manual/src/docs/asciidoc/images/servlet/architecture/filterchainproxy.svg new file mode 100644 index 0000000000..0a860fc95d --- /dev/null +++ b/docs/manual/src/docs/asciidoc/images/servlet/architecture/filterchainproxy.svg @@ -0,0 +1,809 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + DelegatingFilterProxy + + + + DelegatingFilterProxy + + + + + + + + + + + + + + + + + + + + + + + + Client + + + + Client + + + + + + + + + + + + + + + + + + + + + + + + Servlet + + + + Servlet + + + + + + + + + + + + + + + + + + + + + + + + Filter0 + + + + Filter0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Filter2 + + + + Filter2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + FilterChain + + + + + + + + FilterChainProxy + + + + + + + + + + + + + + + + + + + + + + + + Security Filter0 + + + + Security Filter0 + + + + + + + + + + + + + + + + + + + + + + + + Security Filtern + + + + Security Filtern + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SecurityFilterChain + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/manual/src/docs/asciidoc/images/servlet/architecture/multi-securityfilterchain.odg b/docs/manual/src/docs/asciidoc/images/servlet/architecture/multi-securityfilterchain.odg new file mode 100644 index 0000000000..6463ca1782 Binary files /dev/null and b/docs/manual/src/docs/asciidoc/images/servlet/architecture/multi-securityfilterchain.odg differ diff --git a/docs/manual/src/docs/asciidoc/images/servlet/architecture/multi-securityfilterchain.svg b/docs/manual/src/docs/asciidoc/images/servlet/architecture/multi-securityfilterchain.svg new file mode 100644 index 0000000000..a58cb2fb05 --- /dev/null +++ b/docs/manual/src/docs/asciidoc/images/servlet/architecture/multi-securityfilterchain.svg @@ -0,0 +1,1060 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + DelegatingFilterProxy + + + + DelegatingFilterProxy + + + + + + + + + + + + + + + + + + + + + + + + Client + + + + Client + + + + + + + + + + + + + + + + + + + + + + + + Servlet + + + + Servlet + + + + + + + + + + + + + + + + + + + + + + + + Filter0 + + + + Filter0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Filter2 + + + + Filter2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + FilterChain + + + + + + + + FilterChainProxy + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SecurityFilterChain0 + + + + + + + + + + + + + + + + + + + + + + + + + + + /api/** + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SecurityFilterChainn + + + + + + + + + + + + + + + + + + + + /** + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ? + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file