Reduce folders
This commit is contained in:
parent
2da377ec88
commit
0b587dcef1
|
@ -1,20 +1,20 @@
|
|||
* Overview
|
||||
** xref:prerequisites.adoc[Prerequisites]
|
||||
** xref:community.adoc[Community]
|
||||
** xref:whats-new.adoc[What's New]
|
||||
** xref:getting-spring-security.adoc[Getting Spring Security]
|
||||
** xref:features/index.adoc[Features]
|
||||
*** xref:features/authentication/index.adoc[Authentication]
|
||||
**** xref:features/authentication/password-storage.adoc[Password Storage]
|
||||
*** xref:features/exploits/index.adoc[Protection Against Exploits]
|
||||
**** xref:features/exploits/csrf.adoc[CSRF]
|
||||
**** xref:features/exploits/headers.adoc[HTTP Headers]
|
||||
**** xref:features/exploits/http.adoc[HTTP Requests]
|
||||
** xref:modules.adoc[Project Modules & Dependencies]
|
||||
** xref:samples.adoc[Samples]
|
||||
* xref:index.adoc[Overview]
|
||||
* xref:prerequisites.adoc[Prerequisites]
|
||||
* xref:community.adoc[Community]
|
||||
* xref:whats-new.adoc[What's New]
|
||||
* xref:getting-spring-security.adoc[Getting Spring Security]
|
||||
* xref:features/index.adoc[Features]
|
||||
** xref:features/authentication/index.adoc[Authentication]
|
||||
*** xref:features/authentication/password-storage.adoc[Password Storage]
|
||||
** xref:features/exploits/index.adoc[Protection Against Exploits]
|
||||
*** xref:features/exploits/csrf.adoc[CSRF]
|
||||
*** xref:features/exploits/headers.adoc[HTTP Headers]
|
||||
*** xref:features/exploits/http.adoc[HTTP Requests]
|
||||
* xref:modules.adoc[Project Modules & Dependencies]
|
||||
* xref:samples.adoc[Samples]
|
||||
* xref:servlet/index.adoc[Servlet Applications]
|
||||
** xref:servlet/hello/index.adoc[Hello Spring Security]
|
||||
** xref:servlet/architecture/index.adoc[The Big Picture]
|
||||
** xref:servlet/getting-started.adoc[Getting Started]
|
||||
** xref:servlet/architecture.adoc[The Big Picture]
|
||||
** Authentication
|
||||
*** xref:servlet/authentication/architecture/index.adoc[Authentication Architecture]
|
||||
*** xref:servlet/authentication/unpwd/index.adoc[Username/Password]
|
||||
|
@ -69,13 +69,13 @@
|
|||
*** xref:servlet/integrations/cors.adoc[Spring's CORS Support]
|
||||
*** xref:servlet/integrations/jsp-taglibs.adoc[JSP Taglib]
|
||||
** Configuration
|
||||
*** xref:servlet/java-configuration/index.adoc[Java Configuration]
|
||||
*** xref:servlet/kotlin-configuration/index.adoc[Kotlin Configuration]
|
||||
*** xref:servlet/namespace/index.adoc[Namespace Configuration]
|
||||
*** xref:servlet/java-configuration.adoc[Java Configuration]
|
||||
*** xref:servlet/kotlin-configuration.adoc[Kotlin Configuration]
|
||||
*** xref:servlet/xml-namespace.adoc[Namespace Configuration]
|
||||
** xref:servlet/test/index.adoc[Testing]
|
||||
*** xref:servlet/test/method.adoc[Method Security]
|
||||
*** xref:servlet/test/mockmvc.adoc[MockMvc Support]
|
||||
** xref:servlet/crypto/index.adoc[Cryptography]
|
||||
** xref:servlet/cryptography.adoc[Cryptography]
|
||||
** xref:servlet/appendix/index.adoc[Appendix]
|
||||
*** xref:servlet/appendix/database-schema.adoc[Database Schemas]
|
||||
*** xref:servlet/appendix/namespace.adoc[XML Namespace]
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[[appendix-namespace]]
|
||||
= The Security Namespace
|
||||
This appendix provides a reference to the elements available in the security namespace and information on the underlying beans they create (a knowledge of the individual classes and how they work together is assumed - you can find more information in the project Javadoc and elsewhere in this document).
|
||||
If you haven't used the namespace before, please read the xref:servlet/namespace/index.adoc#ns-config[introductory chapter] on namespace configuration, as this is intended as a supplement to the information there.
|
||||
If you haven't used the namespace before, please read the xref:servlet/xml-namespace.adoc#ns-config[introductory chapter] on namespace configuration, as this is intended as a supplement to the information there.
|
||||
Using a good quality XML editor while editing a configuration based on the schema is recommended as this will provide contextual information on which elements and attributes are available as well as comments explaining their purpose.
|
||||
The namespace is written in https://relaxng.org/[RELAX NG] Compact format and later converted into an XSD schema.
|
||||
If you are familiar with this format, you may wish to examine the https://raw.githubusercontent.com/spring-projects/spring-security/main/config/src/main/resources/org/springframework/security/config/spring-security-4.1.rnc[schema file] directly.
|
||||
|
@ -19,10 +19,10 @@ This may include sensitive information, such as request parameters or headers, a
|
|||
=== <http>
|
||||
If you use an `<http>` element within your application, a `FilterChainProxy` bean named "springSecurityFilterChain" is created and the configuration within the element is used to build a filter chain within
|
||||
`FilterChainProxy`.
|
||||
As of Spring Security 3.1, additional `http` elements can be used to add extra filter chains footnote:[See the pass:specialcharacters,macros[xref:servlet/namespace/index.adoc#ns-web-xml[introductory chapter]] for how to set up the mapping from your `web.xml` ].
|
||||
As of Spring Security 3.1, additional `http` elements can be used to add extra filter chains footnote:[See the pass:specialcharacters,macros[xref:servlet/xml-namespace.adoc#ns-web-xml[introductory chapter]] for how to set up the mapping from your `web.xml` ].
|
||||
Some core filters are always created in a filter chain and others will be added to the stack depending on the attributes and child elements which are present.
|
||||
The positions of the standard filters are fixed (see
|
||||
xref:servlet/namespace/index.adoc#filter-stack[the filter order table] in the namespace introduction), removing a common source of errors with previous versions of the framework when users had to configure the filter chain explicitly in the
|
||||
xref:servlet/xml-namespace.adoc#filter-stack[the filter order table] in the namespace introduction), removing a common source of errors with previous versions of the framework when users had to configure the filter chain explicitly in the
|
||||
`FilterChainProxy` bean.
|
||||
You can, of course, still do this if you need full control of the configuration.
|
||||
|
||||
|
@ -179,7 +179,7 @@ The default value is true.
|
|||
[[nsa-access-denied-handler]]
|
||||
=== <access-denied-handler>
|
||||
This element allows you to set the `errorPage` property for the default `AccessDeniedHandler` used by the `ExceptionTranslationFilter`, using the <<nsa-access-denied-handler-error-page,error-page>> attribute, or to supply your own implementation using the<<nsa-access-denied-handler-ref,ref>> attribute.
|
||||
This is discussed in more detail in the section on the xref:servlet/architecture/index.adoc#servlet-exceptiontranslationfilter[ExceptionTranslationFilter].
|
||||
This is discussed in more detail in the section on the xref:servlet/architecture.adoc#servlet-exceptiontranslationfilter[ExceptionTranslationFilter].
|
||||
|
||||
|
||||
[[nsa-access-denied-handler-parents]]
|
||||
|
@ -710,7 +710,7 @@ Default is any HTTP method except "GET", "TRACE", "HEAD", "OPTIONS".
|
|||
=== <custom-filter>
|
||||
This element is used to add a filter to the filter chain.
|
||||
It doesn't create any additional beans but is used to select a bean of type `javax.servlet.Filter` which is already defined in the application context and add that at a particular position in the filter chain maintained by Spring Security.
|
||||
Full details can be found in the xref:servlet/namespace/index.adoc#ns-custom-filters[ namespace chapter].
|
||||
Full details can be found in the xref:servlet/xml-namespace.adoc#ns-custom-filters[ namespace chapter].
|
||||
|
||||
|
||||
[[nsa-custom-filter-parents]]
|
||||
|
|
|
@ -0,0 +1,248 @@
|
|||
[[servlet-architecture]]
|
||||
= Servlet Security: The Big Picture
|
||||
:figures: servlet/architecture
|
||||
|
||||
This section discusses Spring Security's high level architecture within Servlet based applications.
|
||||
We build on this high level understanding within xref:servlet/authentication/index.adoc#servlet-authentication[Authentication], xref:servlet/authorization/index.adoc#servlet-authorization[Authorization], xref:servlet/exploits/index.adoc#servlet-exploits[Protection Against Exploits] sections 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.png[]
|
||||
|
||||
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.
|
||||
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`.
|
||||
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
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
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
|
||||
}
|
||||
----
|
||||
|
||||
.Kotlin
|
||||
[source,kotlin,role="secondary"]
|
||||
----
|
||||
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` 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 {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``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 <<servlet-filters-review,``Filter``s and the `FilterChain`>>.
|
||||
|
||||
.DelegatingFilterProxy
|
||||
[[servlet-delegatingfilterproxy-figure]]
|
||||
image::{figures}/delegatingfilterproxy.png[]
|
||||
|
||||
`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
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary",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 <<servlet-delegatingfilterproxy-figure>> `delegate` is an instance of __Bean Filter~0~__
|
||||
Filter delegate = getFilterBean(someBeanName);
|
||||
// delegate work to the Spring Bean
|
||||
delegate.doFilter(request, response);
|
||||
}
|
||||
----
|
||||
|
||||
.Kotlin
|
||||
[source,kotlin,role="secondary",subs="+quotes,+macros"]
|
||||
----
|
||||
fun doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain) {
|
||||
// Lazily get Filter that was registered as a Spring Bean
|
||||
// For the example in <<servlet-delegatingfilterproxy-figure>> `delegate` is an instance of __Bean Filter~0~__
|
||||
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 `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 <<servlet-securityfilterchain,`SecurityFilterChain`>>.
|
||||
Since `FilterChainProxy` is a Bean, it is typically wrapped in a <<servlet-delegatingfilterproxy>>.
|
||||
|
||||
.FilterChainProxy
|
||||
[[servlet-filterchainproxy-figure]]
|
||||
image::{figures}/filterchainproxy.png[]
|
||||
|
||||
[[servlet-securityfilterchain]]
|
||||
== SecurityFilterChain
|
||||
|
||||
{security-api-url}org/springframework/security/web/SecurityFilterChain.html[`SecurityFilterChain`] is used by <<servlet-filterchainproxy>> to determine which Spring Security ``Filter``s should be invoked for this request.
|
||||
|
||||
.SecurityFilterChain
|
||||
[[servlet-securityfilterchain-figure]]
|
||||
image::{figures}/securityfilterchain.png[]
|
||||
|
||||
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 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.
|
||||
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 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_ of your application.
|
||||
|
||||
.Multiple SecurityFilterChain
|
||||
[[servlet-multi-securityfilterchain-figure]]
|
||||
image::{figures}/multi-securityfilterchain.png[]
|
||||
|
||||
In the <<servlet-multi-securityfilterchain-figure>> 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 Security Filters are inserted into the <<servlet-filterchainproxy>> with the <<servlet-securityfilterchain>> API.
|
||||
The <<servlet-filters-review,order of ``Filter``>>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
|
||||
* WebAsyncManagerIntegrationFilter
|
||||
* SecurityContextPersistenceFilter
|
||||
* HeaderWriterFilter
|
||||
* CorsFilter
|
||||
* CsrfFilter
|
||||
* LogoutFilter
|
||||
* OAuth2AuthorizationRequestRedirectFilter
|
||||
* Saml2WebSsoAuthenticationRequestFilter
|
||||
* X509AuthenticationFilter
|
||||
* AbstractPreAuthenticatedProcessingFilter
|
||||
* CasAuthenticationFilter
|
||||
* OAuth2LoginAuthenticationFilter
|
||||
* Saml2WebSsoAuthenticationFilter
|
||||
* xref:servlet/authentication/unpwd/form.adoc#servlet-authentication-usernamepasswordauthenticationfilter[`UsernamePasswordAuthenticationFilter`]
|
||||
* OpenIDAuthenticationFilter
|
||||
* DefaultLoginPageGeneratingFilter
|
||||
* DefaultLogoutPageGeneratingFilter
|
||||
* ConcurrentSessionFilter
|
||||
* xref:servlet/authentication/unpwd/digest.adoc#servlet-authentication-digest[`DigestAuthenticationFilter`]
|
||||
* BearerTokenAuthenticationFilter
|
||||
* xref:servlet/authentication/unpwd/basic.adoc#servlet-authentication-basic[`BasicAuthenticationFilter`]
|
||||
* RequestCacheAwareFilter
|
||||
* SecurityContextHolderAwareRequestFilter
|
||||
* JaasApiIntegrationFilter
|
||||
* RememberMeAuthenticationFilter
|
||||
* AnonymousAuthenticationFilter
|
||||
* OAuth2AuthorizationCodeGrantFilter
|
||||
* SessionManagementFilter
|
||||
* <<servlet-exceptiontranslationfilter,`ExceptionTranslationFilter`>>
|
||||
* xref:servlet/authorization/authorize-requests.adoc#servlet-authorization-filtersecurityinterceptor[`FilterSecurityInterceptor`]
|
||||
* SwitchUserFilter
|
||||
|
||||
[[servlet-exceptiontranslationfilter]]
|
||||
== Handling Security Exceptions
|
||||
|
||||
|
||||
The {security-api-url}org/springframework/security/web/access/ExceptionTranslationFilter.html[`ExceptionTranslationFilter`] allows translation of {security-api-url}org/springframework/security/access/AccessDeniedException.html[`AccessDeniedException`] and {security-api-url}/org/springframework/security/core/AuthenticationException.html[`AuthenticationException`] into HTTP responses.
|
||||
|
||||
`ExceptionTranslationFilter` is inserted into the <<servlet-filterchainproxy>> as one of the <<servlet-security-filters>>.
|
||||
|
||||
image::{figures}/exceptiontranslationfilter.png[]
|
||||
|
||||
|
||||
* 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__.
|
||||
** The xref:servlet/authentication/architecture/index.adoc#servlet-authentication-securitycontextholder[SecurityContextHolder] is cleared out
|
||||
** The `HttpServletRequest` is saved in the {security-api-url}org/springframework/security/web/savedrequest/RequestCache.html[`RequestCache`].
|
||||
When the user successfully authenticates, the `RequestCache` is used to replay the original request.
|
||||
// FIXME: add link to authentication success
|
||||
** The `AuthenticationEntryPoint` is used to request credentials from the client.
|
||||
For example, it might redirect to a log in page or send a `WWW-Authenticate` header.
|
||||
// FIXME: link to AuthenticationEntryPoint
|
||||
* image:{icondir}/number_3.png[] Otherwise if it is an `AccessDeniedException`, then __Access Denied__.
|
||||
The `AccessDeniedHandler` is invoked to handle access denied.
|
||||
// FIXME: link to AccessDeniedHandler
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
If the application does not throw an `AccessDeniedException` or an `AuthenticationException`, then `ExceptionTranslationFilter` does not do anything.
|
||||
====
|
||||
|
||||
The pseudocode for `ExceptionTranslationFilter` looks something like this:
|
||||
|
||||
.ExceptionTranslationFilter pseudocode
|
||||
[source,java]
|
||||
----
|
||||
try {
|
||||
filterChain.doFilter(request, response); // <1>
|
||||
} catch (AccessDeniedException | AuthenticationException ex) {
|
||||
if (!authenticated || ex instanceof AuthenticationException) {
|
||||
startAuthentication(); // <2>
|
||||
} else {
|
||||
accessDenied(); // <3>
|
||||
}
|
||||
}
|
||||
----
|
||||
<1> You will recall from <<servlet-filters-review>> that invoking `FilterChain.doFilter(request, response)` is the equivalent of invoking the rest of the application.
|
||||
This means that if another part of the application, (i.e. xref:servlet/authorization/authorize-requests.adoc#servlet-authorization-filtersecurityinterceptor[`FilterSecurityInterceptor`] or method security) throws an `AuthenticationException` or `AccessDeniedException` it will be caught and handled here.
|
||||
<2> If the user is not authenticated or it is an `AuthenticationException`, then __Start Authentication__.
|
||||
<3> Otherwise, __Access Denied__
|
|
@ -2,7 +2,7 @@
|
|||
= Servlet Authentication Architecture
|
||||
:figures: servlet/authentication/architecture
|
||||
|
||||
This discussion expands on xref:servlet/architecture/index.adoc#servlet-architecture[Servlet Security: The Big Picture] to describe the main architectural components of Spring Security's used in Servlet authentication.
|
||||
This discussion expands on xref:servlet/architecture.adoc#servlet-architecture[Servlet Security: The Big Picture] to describe the main architectural components of Spring Security's used in Servlet authentication.
|
||||
If you need concrete flows that explain how these pieces fit together, look at the xref:servlet/authentication/index.adoc#servlet-authentication-mechanisms[Authentication Mechanism] specific sections.
|
||||
|
||||
* <<servlet-authentication-securitycontextholder>> - The `SecurityContextHolder` is where Spring Security stores the details of who is xref:features/authentication/index.adoc#authentication[authenticated].
|
||||
|
@ -94,7 +94,7 @@ val authorities = authentication.authorities
|
|||
|
||||
By default the `SecurityContextHolder` uses a `ThreadLocal` to store these details, which means that the `SecurityContext` is always available to methods in the same thread, even if the `SecurityContext` is not explicitly passed around as an argument to those methods.
|
||||
Using a `ThreadLocal` in this way is quite safe if care is taken to clear the thread after the present principal's request is processed.
|
||||
Spring Security's xref:servlet/architecture/index.adoc#servlet-filterchainproxy[FilterChainProxy] ensures that the `SecurityContext` is always cleared.
|
||||
Spring Security's xref:servlet/architecture.adoc#servlet-filterchainproxy[FilterChainProxy] ensures that the `SecurityContext` is always cleared.
|
||||
|
||||
Some applications aren't entirely suitable for using a `ThreadLocal`, because of the specific way they work with threads.
|
||||
For example, a Swing client might want all threads in a Java Virtual Machine to use the same security context.
|
||||
|
@ -152,7 +152,7 @@ Of course, Spring Security is expressly designed to handle this common requireme
|
|||
== AuthenticationManager
|
||||
|
||||
{security-api-url}org/springframework/security/authentication/AuthenticationManager.html[`AuthenticationManager`] is the API that defines how Spring Security's Filters perform xref:features/authentication/index.adoc#authentication[authentication].
|
||||
The <<servlet-authentication-authentication,`Authentication`>> that is returned is then set on the <<servlet-authentication-securitycontextholder>> by the controller (i.e. xref:servlet/architecture/index.adoc#servlet-security-filters[Spring Security's ``Filters``s]) that invoked the `AuthenticationManager`.
|
||||
The <<servlet-authentication-authentication,`Authentication`>> that is returned is then set on the <<servlet-authentication-securitycontextholder>> by the controller (i.e. xref:servlet/architecture.adoc#servlet-security-filters[Spring Security's ``Filters``s]) that invoked the `AuthenticationManager`.
|
||||
If you are not integrating with __Spring Security's ``Filters``s__ you can set the `SecurityContextHolder` directly and are not required to use an `AuthenticationManager`.
|
||||
|
||||
While the implementation of `AuthenticationManager` could be anything, the most common implementation is <<servlet-authentication-providermanager,`ProviderManager`>>.
|
||||
|
@ -179,7 +179,7 @@ The parent can be any type of `AuthenticationManager`, but it is often an instan
|
|||
image::{figures}/providermanager-parent.png[]
|
||||
|
||||
In fact, multiple `ProviderManager` instances might share the same parent `AuthenticationManager`.
|
||||
This is somewhat common in scenarios where there are multiple xref:servlet/architecture/index.adoc#servlet-securityfilterchain[`SecurityFilterChain`] instances that have some authentication in common (the shared parent `AuthenticationManager`), but also different authentication mechanisms (the different `ProviderManager` instances).
|
||||
This is somewhat common in scenarios where there are multiple xref:servlet/architecture.adoc#servlet-securityfilterchain[`SecurityFilterChain`] instances that have some authentication in common (the shared parent `AuthenticationManager`), but also different authentication mechanisms (the different `ProviderManager` instances).
|
||||
|
||||
image::{figures}/providermanagers-parent.png[]
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
= Authentication
|
||||
|
||||
Spring Security provides comprehensive support for xref:features/authentication/index.adoc#authentication[Authentication].
|
||||
We start by discussing the overall xref:servlet/architecture/index.adoc#servlet-architecture[Servlet Authentication Architecture].
|
||||
We start by discussing the overall xref:servlet/architecture.adoc#servlet-architecture[Servlet Authentication Architecture].
|
||||
As you might expect, this section is more abstract describing the architecture without much discussion on how it applies to concrete flows.
|
||||
|
||||
If you prefer, you can refer to <<servlet-authentication-mechanisms,Authentication Mechanisms>> for concrete ways in which users can authenticate.
|
||||
|
|
|
@ -139,7 +139,7 @@ A typical configuration using this filter would look like this:
|
|||
</security:authentication-manager>
|
||||
----
|
||||
|
||||
We've assumed here that the xref:servlet/namespace/index.adoc#ns-config[security namespace] is being used for configuration.
|
||||
We've assumed here that the xref:servlet/xml-namespace.adoc#ns-config[security namespace] is being used for configuration.
|
||||
It's also assumed that you have added a `UserDetailsService` (called "userDetailsService") to your configuration to load the user's roles.
|
||||
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ If a principal is aware a token has been captured, they can easily change their
|
|||
If more significant security is needed you should use the approach described in the next section.
|
||||
Alternatively, remember-me services should simply not be used at all.
|
||||
|
||||
If you are familiar with the topics discussed in the chapter on xref:servlet/namespace/index.adoc#ns-config[namespace configuration], you can enable remember-me authentication just by adding the `<remember-me>` element:
|
||||
If you are familiar with the topics discussed in the chapter on xref:servlet/xml-namespace.adoc#ns-config[namespace configuration], you can enable remember-me authentication just by adding the `<remember-me>` element:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
|
|
|
@ -11,13 +11,13 @@ First, we see the https://tools.ietf.org/html/rfc7235#section-4.1[WWW-Authentica
|
|||
.Sending WWW-Authenticate Header
|
||||
image::{figures}/basicauthenticationentrypoint.png[]
|
||||
|
||||
The figure builds off our xref:servlet/architecture/index.adoc#servlet-securityfilterchain[`SecurityFilterChain`] diagram.
|
||||
The figure builds off our xref:servlet/architecture.adoc#servlet-securityfilterchain[`SecurityFilterChain`] diagram.
|
||||
|
||||
image:{icondir}/number_1.png[] First, a user makes an unauthenticated request to the resource `/private` for which it is not authorized.
|
||||
|
||||
image:{icondir}/number_2.png[] Spring Security's xref:servlet/authorization/authorize-requests.adoc#servlet-authorization-filtersecurityinterceptor[`FilterSecurityInterceptor`] indicates that the unauthenticated request is __Denied__ by throwing an `AccessDeniedException`.
|
||||
|
||||
image:{icondir}/number_3.png[] Since the user is not authenticated, xref:servlet/architecture/index.adoc#servlet-exceptiontranslationfilter[`ExceptionTranslationFilter`] initiates __Start Authentication__.
|
||||
image:{icondir}/number_3.png[] Since the user is not authenticated, xref:servlet/architecture.adoc#servlet-exceptiontranslationfilter[`ExceptionTranslationFilter`] initiates __Start Authentication__.
|
||||
The configured xref:servlet/authentication/architecture/index.adoc#servlet-authentication-authenticationentrypoint[`AuthenticationEntryPoint`] is an instance of {security-api-url}org/springframework/security/web/authentication/www/BasicAuthenticationEntryPoint.html[`BasicAuthenticationEntryPoint`] which sends a WWW-Authenticate header.
|
||||
The `RequestCache` is typically a `NullRequestCache` that does not save the request since the client is capable of replaying the requests it originally requested.
|
||||
|
||||
|
@ -28,7 +28,7 @@ Below is the flow for the username and password being processed.
|
|||
.Authenticating Username and Password
|
||||
image::{figures}/basicauthenticationfilter.png[]
|
||||
|
||||
The figure builds off our xref:servlet/architecture/index.adoc#servlet-securityfilterchain[`SecurityFilterChain`] diagram.
|
||||
The figure builds off our xref:servlet/architecture.adoc#servlet-securityfilterchain[`SecurityFilterChain`] diagram.
|
||||
|
||||
|
||||
image:{icondir}/number_1.png[] When the user submits their username and password, the `BasicAuthenticationFilter` creates a `UsernamePasswordAuthenticationToken` which is a type of xref:servlet/authentication/architecture/index.adoc#servlet-authentication-authentication[`Authentication`] by extracting the username and password from the `HttpServletRequest`.
|
||||
|
|
|
@ -12,13 +12,13 @@ First, we see how the user is redirected to the log in form.
|
|||
.Redirecting to the Log In Page
|
||||
image::{figures}/loginurlauthenticationentrypoint.png[]
|
||||
|
||||
The figure builds off our xref:servlet/architecture/index.adoc#servlet-securityfilterchain[`SecurityFilterChain`] diagram.
|
||||
The figure builds off our xref:servlet/architecture.adoc#servlet-securityfilterchain[`SecurityFilterChain`] diagram.
|
||||
|
||||
image:{icondir}/number_1.png[] First, a user makes an unauthenticated request to the resource `/private` for which it is not authorized.
|
||||
|
||||
image:{icondir}/number_2.png[] Spring Security's xref:servlet/authorization/authorize-requests.adoc#servlet-authorization-filtersecurityinterceptor[`FilterSecurityInterceptor`] indicates that the unauthenticated request is __Denied__ by throwing an `AccessDeniedException`.
|
||||
|
||||
image:{icondir}/number_3.png[] Since the user is not authenticated, xref:servlet/architecture/index.adoc#servlet-exceptiontranslationfilter[`ExceptionTranslationFilter`] initiates __Start Authentication__ and sends a redirect to the log in page with the configured xref:servlet/authentication/architecture/index.adoc#servlet-authentication-authenticationentrypoint[`AuthenticationEntryPoint`].
|
||||
image:{icondir}/number_3.png[] Since the user is not authenticated, xref:servlet/architecture.adoc#servlet-exceptiontranslationfilter[`ExceptionTranslationFilter`] initiates __Start Authentication__ and sends a redirect to the log in page with the configured xref:servlet/authentication/architecture/index.adoc#servlet-authentication-authenticationentrypoint[`AuthenticationEntryPoint`].
|
||||
In most cases the `AuthenticationEntryPoint` is an instance of {security-api-url}org/springframework/security/web/authentication/LoginUrlAuthenticationEntryPoint.html[`LoginUrlAuthenticationEntryPoint`].
|
||||
|
||||
image:{icondir}/number_4.png[] The browser will then request the log in page that it was redirected to.
|
||||
|
@ -32,7 +32,7 @@ The `UsernamePasswordAuthenticationFilter` extends xref:servlet/authentication/a
|
|||
.Authenticating Username and Password
|
||||
image::{figures}/usernamepasswordauthenticationfilter.png[]
|
||||
|
||||
The figure builds off our xref:servlet/architecture/index.adoc#servlet-securityfilterchain[`SecurityFilterChain`] diagram.
|
||||
The figure builds off our xref:servlet/architecture.adoc#servlet-securityfilterchain[`SecurityFilterChain`] diagram.
|
||||
|
||||
|
||||
image:{icondir}/number_1.png[] When the user submits their username and password, the `UsernamePasswordAuthenticationFilter` creates a `UsernamePasswordAuthenticationToken` which is a type of xref:servlet/authentication/architecture/index.adoc#servlet-authentication-authentication[`Authentication`] by extracting the username and password from the `HttpServletRequest`.
|
||||
|
@ -59,7 +59,7 @@ image:{icondir}/number_4.png[] If authentication is successful, then __Success__
|
|||
If remember me is not configured, this is a no-op.
|
||||
// FIXME: link to rememberme
|
||||
* `ApplicationEventPublisher` publishes an `InteractiveAuthenticationSuccessEvent`.
|
||||
* The `AuthenticationSuccessHandler` is invoked. Typically this is a `SimpleUrlAuthenticationSuccessHandler` which will redirect to a request saved by xref:servlet/architecture/index.adoc#servlet-exceptiontranslationfilter[`ExceptionTranslationFilter`] when we redirect to the log in page.
|
||||
* The `AuthenticationSuccessHandler` is invoked. Typically this is a `SimpleUrlAuthenticationSuccessHandler` which will redirect to a request saved by xref:servlet/architecture.adoc#servlet-exceptiontranslationfilter[`ExceptionTranslationFilter`] when we redirect to the log in page.
|
||||
|
||||
[[servlet-authentication-form-min]]
|
||||
Spring Security form log in is enabled by default.
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
= Authorize HttpServletRequest with FilterSecurityInterceptor
|
||||
:figures: servlet/authorization
|
||||
|
||||
This section builds on xref:servlet/architecture/index.adoc#servlet-architecture[Servlet Architecture and Implementation] by digging deeper into how xref:servlet/authorization/index.adoc#servlet-authorization[authorization] works within Servlet based applications.
|
||||
This section builds on xref:servlet/architecture.adoc#servlet-architecture[Servlet Architecture and Implementation] by digging deeper into how xref:servlet/authorization/index.adoc#servlet-authorization[authorization] works within Servlet based applications.
|
||||
|
||||
The {security-api-url}org/springframework/security/web/access/intercept/FilterSecurityInterceptor.html[`FilterSecurityInterceptor`] provides xref:servlet/authorization/index.adoc#servlet-authorization[authorization] for ``HttpServletRequest``s.
|
||||
It is inserted into the xref:servlet/architecture/index.adoc#servlet-filterchainproxy[FilterChainProxy] as one of the xref:servlet/architecture/index.adoc#servlet-security-filters[Security Filters].
|
||||
It is inserted into the xref:servlet/architecture.adoc#servlet-filterchainproxy[FilterChainProxy] as one of the xref:servlet/architecture.adoc#servlet-security-filters[Security Filters].
|
||||
|
||||
.Authorize HttpServletRequest
|
||||
image::{figures}/filtersecurityinterceptor.png[]
|
||||
|
@ -16,8 +16,8 @@ image::{figures}/filtersecurityinterceptor.png[]
|
|||
* image:{icondir}/number_3.png[] Next, it passes the `FilterInvocation` to `SecurityMetadataSource` to get the ``ConfigAttribute``s.
|
||||
* image:{icondir}/number_4.png[] Finally, it passes the `Authentication`, `FilterInvocation`, and ``ConfigAttribute``s to the `AccessDecisionManager`.
|
||||
** image:{icondir}/number_5.png[] If authorization is denied, an `AccessDeniedException` is thrown.
|
||||
In this case the xref:servlet/architecture/index.adoc#servlet-exceptiontranslationfilter[`ExceptionTranslationFilter`] handles the `AccessDeniedException`.
|
||||
** image:{icondir}/number_6.png[] If access is granted, `FilterSecurityInterceptor` continues with the xref:servlet/architecture/index.adoc#servlet-filters-review[FilterChain] which allows the application to process normally.
|
||||
In this case the xref:servlet/architecture.adoc#servlet-exceptiontranslationfilter[`ExceptionTranslationFilter`] handles the `AccessDeniedException`.
|
||||
** image:{icondir}/number_6.png[] If access is granted, `FilterSecurityInterceptor` continues with the xref:servlet/architecture.adoc#servlet-filters-review[FilterChain] which allows the application to process normally.
|
||||
|
||||
// configuration (xml/java)
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
[[aop-alliance]]
|
||||
== AOP Alliance (MethodInvocation) Security Interceptor
|
||||
Prior to Spring Security 2.0, securing ``MethodInvocation``s needed quite a lot of boiler plate configuration.
|
||||
Now the recommended approach for method security is to use xref:servlet/namespace/index.adoc#ns-method-security[namespace configuration].
|
||||
Now the recommended approach for method security is to use xref:servlet/xml-namespace.adoc#ns-method-security[namespace configuration].
|
||||
This way the method security infrastructure beans are configured automatically for you so you don't really need to know about the implementation classes.
|
||||
We'll just provide a quick overview of the classes that are involved here.
|
||||
|
||||
|
|
|
@ -0,0 +1,264 @@
|
|||
[[crypto]]
|
||||
= Spring Security Crypto Module
|
||||
|
||||
|
||||
[[spring-security-crypto-introduction]]
|
||||
== Introduction
|
||||
The Spring Security Crypto module provides support for symmetric encryption, key generation, and password encoding.
|
||||
The code is distributed as part of the core module but has no dependencies on any other Spring Security (or Spring) code.
|
||||
|
||||
|
||||
[[spring-security-crypto-encryption]]
|
||||
== Encryptors
|
||||
The Encryptors class provides factory methods for constructing symmetric encryptors.
|
||||
Using this class, you can create ByteEncryptors to encrypt data in raw byte[] form.
|
||||
You can also construct TextEncryptors to encrypt text strings.
|
||||
Encryptors are thread-safe.
|
||||
|
||||
[[spring-security-crypto-encryption-bytes]]
|
||||
=== BytesEncryptor
|
||||
Use the `Encryptors.stronger` factory method to construct a BytesEncryptor:
|
||||
|
||||
.BytesEncryptor
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
Encryptors.stronger("password", "salt");
|
||||
----
|
||||
|
||||
.Kotlin
|
||||
[source,kotlin,role="secondary"]
|
||||
----
|
||||
Encryptors.stronger("password", "salt")
|
||||
----
|
||||
====
|
||||
|
||||
The "stronger" encryption method creates an encryptor using 256 bit AES encryption with
|
||||
Galois Counter Mode (GCM).
|
||||
It derives the secret key using PKCS #5's PBKDF2 (Password-Based Key Derivation Function #2).
|
||||
This method requires Java 6.
|
||||
The password used to generate the SecretKey should be kept in a secure place and not be shared.
|
||||
The salt is used to prevent dictionary attacks against the key in the event your encrypted data is compromised.
|
||||
A 16-byte random initialization vector is also applied so each encrypted message is unique.
|
||||
|
||||
The provided salt should be in hex-encoded String form, be random, and be at least 8 bytes in length.
|
||||
Such a salt may be generated using a KeyGenerator:
|
||||
|
||||
.Generating a key
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
String salt = KeyGenerators.string().generateKey(); // generates a random 8-byte salt that is then hex-encoded
|
||||
----
|
||||
|
||||
.Kotlin
|
||||
[source,kotlin,role="secondary"]
|
||||
----
|
||||
val salt = KeyGenerators.string().generateKey() // generates a random 8-byte salt that is then hex-encoded
|
||||
----
|
||||
====
|
||||
|
||||
Users may also use the `standard` encryption method, which is 256-bit AES in Cipher Block Chaining (CBC) Mode.
|
||||
This mode is not https://en.wikipedia.org/wiki/Authenticated_encryption[authenticated] and does not provide any
|
||||
guarantees about the authenticity of the data.
|
||||
For a more secure alternative, users should prefer `Encryptors.stronger`.
|
||||
|
||||
[[spring-security-crypto-encryption-text]]
|
||||
=== TextEncryptor
|
||||
Use the Encryptors.text factory method to construct a standard TextEncryptor:
|
||||
|
||||
.TextEncryptor
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
Encryptors.text("password", "salt");
|
||||
----
|
||||
|
||||
.Kotlin
|
||||
[source,kotlin,role="secondary"]
|
||||
----
|
||||
Encryptors.text("password", "salt")
|
||||
----
|
||||
====
|
||||
|
||||
A TextEncryptor uses a standard BytesEncryptor to encrypt text data.
|
||||
Encrypted results are returned as hex-encoded strings for easy storage on the filesystem or in the database.
|
||||
|
||||
Use the Encryptors.queryableText factory method to construct a "queryable" TextEncryptor:
|
||||
|
||||
.Queryable TextEncryptor
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
Encryptors.queryableText("password", "salt");
|
||||
----
|
||||
|
||||
.Kotlin
|
||||
[source,kotlin,role="secondary"]
|
||||
----
|
||||
Encryptors.queryableText("password", "salt")
|
||||
----
|
||||
====
|
||||
|
||||
The difference between a queryable TextEncryptor and a standard TextEncryptor has to do with initialization vector (iv) handling.
|
||||
The iv used in a queryable TextEncryptor#encrypt operation is shared, or constant, and is not randomly generated.
|
||||
This means the same text encrypted multiple times will always produce the same encryption result.
|
||||
This is less secure, but necessary for encrypted data that needs to be queried against.
|
||||
An example of queryable encrypted text would be an OAuth apiKey.
|
||||
|
||||
[[spring-security-crypto-keygenerators]]
|
||||
== Key Generators
|
||||
The KeyGenerators class provides a number of convenience factory methods for constructing different types of key generators.
|
||||
Using this class, you can create a BytesKeyGenerator to generate byte[] keys.
|
||||
You can also construct a StringKeyGenerator to generate string keys.
|
||||
KeyGenerators are thread-safe.
|
||||
|
||||
=== BytesKeyGenerator
|
||||
Use the KeyGenerators.secureRandom factory methods to generate a BytesKeyGenerator backed by a SecureRandom instance:
|
||||
|
||||
.BytesKeyGenerator
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
BytesKeyGenerator generator = KeyGenerators.secureRandom();
|
||||
byte[] key = generator.generateKey();
|
||||
----
|
||||
|
||||
.Kotlin
|
||||
[source,kotlin,role="secondary"]
|
||||
----
|
||||
val generator = KeyGenerators.secureRandom()
|
||||
val key = generator.generateKey()
|
||||
----
|
||||
====
|
||||
|
||||
The default key length is 8 bytes.
|
||||
There is also a KeyGenerators.secureRandom variant that provides control over the key length:
|
||||
|
||||
.KeyGenerators.secureRandom
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
KeyGenerators.secureRandom(16);
|
||||
----
|
||||
|
||||
.Kotlin
|
||||
[source,kotlin,role="secondary"]
|
||||
----
|
||||
KeyGenerators.secureRandom(16)
|
||||
----
|
||||
====
|
||||
|
||||
Use the KeyGenerators.shared factory method to construct a BytesKeyGenerator that always returns the same key on every invocation:
|
||||
|
||||
.KeyGenerators.shared
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
KeyGenerators.shared(16);
|
||||
----
|
||||
|
||||
.Kotlin
|
||||
[source,kotlin,role="secondary"]
|
||||
----
|
||||
KeyGenerators.shared(16)
|
||||
----
|
||||
====
|
||||
|
||||
=== StringKeyGenerator
|
||||
Use the KeyGenerators.string factory method to construct a 8-byte, SecureRandom KeyGenerator that hex-encodes each key as a String:
|
||||
|
||||
.StringKeyGenerator
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
KeyGenerators.string();
|
||||
----
|
||||
|
||||
.Kotlin
|
||||
[source,kotlin,role="secondary"]
|
||||
----
|
||||
KeyGenerators.string()
|
||||
----
|
||||
====
|
||||
|
||||
[[spring-security-crypto-passwordencoders]]
|
||||
== Password Encoding
|
||||
The password package of the spring-security-crypto module provides support for encoding passwords.
|
||||
`PasswordEncoder` is the central service interface and has the following signature:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
public interface PasswordEncoder {
|
||||
|
||||
String encode(String rawPassword);
|
||||
|
||||
boolean matches(String rawPassword, String encodedPassword);
|
||||
}
|
||||
----
|
||||
|
||||
The matches method returns true if the rawPassword, once encoded, equals the encodedPassword.
|
||||
This method is designed to support password-based authentication schemes.
|
||||
|
||||
The `BCryptPasswordEncoder` implementation uses the widely supported "bcrypt" algorithm to hash the passwords.
|
||||
Bcrypt uses a random 16 byte salt value and is a deliberately slow algorithm, in order to hinder password crackers.
|
||||
The amount of work it does can be tuned using the "strength" parameter which takes values from 4 to 31.
|
||||
The higher the value, the more work has to be done to calculate the hash.
|
||||
The default value is 10.
|
||||
You can change this value in your deployed system without affecting existing passwords, as the value is also stored in the encoded hash.
|
||||
|
||||
.BCryptPasswordEncoder
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
|
||||
// Create an encoder with strength 16
|
||||
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(16);
|
||||
String result = encoder.encode("myPassword");
|
||||
assertTrue(encoder.matches("myPassword", result));
|
||||
----
|
||||
|
||||
.Kotlin
|
||||
[source,kotlin,role="secondary"]
|
||||
----
|
||||
|
||||
// Create an encoder with strength 16
|
||||
val encoder = BCryptPasswordEncoder(16)
|
||||
val result: String = encoder.encode("myPassword")
|
||||
assertTrue(encoder.matches("myPassword", result))
|
||||
----
|
||||
====
|
||||
|
||||
The `Pbkdf2PasswordEncoder` implementation uses PBKDF2 algorithm to hash the passwords.
|
||||
In order to defeat password cracking PBKDF2 is a deliberately slow algorithm and should be tuned to take about .5 seconds to verify a password on your system.
|
||||
|
||||
|
||||
.Pbkdf2PasswordEncoder
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
// Create an encoder with all the defaults
|
||||
Pbkdf2PasswordEncoder encoder = new Pbkdf2PasswordEncoder();
|
||||
String result = encoder.encode("myPassword");
|
||||
assertTrue(encoder.matches("myPassword", result));
|
||||
----
|
||||
|
||||
.Kotlin
|
||||
[source,kotlin,role="secondary"]
|
||||
----
|
||||
// Create an encoder with all the defaults
|
||||
val encoder = Pbkdf2PasswordEncoder()
|
||||
val result: String = encoder.encode("myPassword")
|
||||
assertTrue(encoder.matches("myPassword", result))
|
||||
----
|
||||
====
|
|
@ -0,0 +1,74 @@
|
|||
[[servlet-hello]]
|
||||
= Hello Spring Security
|
||||
|
||||
This section covers the minimum setup for how to use Spring Security with Spring Boot.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
The completed application can be found {gh-samples-url}/servlet/spring-boot/java/hello-security[in our samples repository].
|
||||
For your convenience, you can download a minimal Spring Boot + Spring Security application by https://start.spring.io/starter.zip?type=maven-project&language=java&packaging=jar&jvmVersion=1.8&groupId=example&artifactId=hello-security&name=hello-security&description=Hello%20Security&packageName=example.hello-security&dependencies=web,security[clicking here].
|
||||
====
|
||||
|
||||
[[servlet-hello-dependencies]]
|
||||
== Updating Dependencies
|
||||
|
||||
The only step you need to do is update the dependencies by using xref:getting-spring-security.adoc#getting-maven-boot[Maven] or xref:getting-spring-security.adoc#getting-gradle-boot[Gradle].
|
||||
|
||||
[[servlet-hello-starting]]
|
||||
== Starting Hello Spring Security Boot
|
||||
|
||||
You can now https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#using-boot-running-with-the-maven-plugin[run the Spring Boot application] by using the Maven Plugin's `run` goal.
|
||||
The following example shows how to do so (and the beginning of the output from doing so):
|
||||
|
||||
.Running Spring Boot Application
|
||||
====
|
||||
[source,bash]
|
||||
----
|
||||
$ ./mvn spring-boot:run
|
||||
...
|
||||
INFO 23689 --- [ restartedMain] .s.s.UserDetailsServiceAutoConfiguration :
|
||||
|
||||
Using generated security password: 8e557245-73e2-4286-969a-ff57fe326336
|
||||
|
||||
...
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
[[servlet-hello-auto-configuration]]
|
||||
== Spring Boot Auto Configuration
|
||||
|
||||
// FIXME: Link to relevant portions of documentation
|
||||
// FIXME: Link to Spring Boot's Security Auto configuration classes
|
||||
// FIXME: Add a links for what user's should do next
|
||||
|
||||
Spring Boot automatically:
|
||||
|
||||
* Enables Spring Security's default configuration, which creates a servlet `Filter` as a bean named `springSecurityFilterChain`.
|
||||
This bean is responsible for all the security (protecting the application URLs, validating submitted username and passwords, redirecting to the log in form, and so on) within your application.
|
||||
* Creates a `UserDetailsService` bean with a username of `user` and a randomly generated password that is logged to the console.
|
||||
* Registers the `Filter` with a bean named `springSecurityFilterChain` with the Servlet container for every request.
|
||||
|
||||
Spring Boot is not configuring much, but it does a lot.
|
||||
A summary of the features follows:
|
||||
|
||||
* Require an authenticated user for any interaction with the application
|
||||
* Generate a default login form for you
|
||||
* Let the user with a username of `user` and a password that is logged to the console to authenticate with form-based authentication (in the preceding example, the password is `8e557245-73e2-4286-969a-ff57fe326336`)
|
||||
* Protects the password storage with BCrypt
|
||||
* Lets the user log out
|
||||
* https://en.wikipedia.org/wiki/Cross-site_request_forgery[CSRF attack] prevention
|
||||
* https://en.wikipedia.org/wiki/Session_fixation[Session Fixation] protection
|
||||
* Security Header integration
|
||||
** https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security[HTTP Strict Transport Security] for secure requests
|
||||
** https://msdn.microsoft.com/en-us/library/ie/gg622941(v=vs.85).aspx[X-Content-Type-Options] integration
|
||||
** Cache Control (can be overridden later by your application to allow caching of your static resources)
|
||||
** https://msdn.microsoft.com/en-us/library/dd565647(v=vs.85).aspx[X-XSS-Protection] integration
|
||||
** X-Frame-Options integration to help prevent https://en.wikipedia.org/wiki/Clickjacking[Clickjacking]
|
||||
* Integrate with the following Servlet API methods:
|
||||
** https://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#getRemoteUser()[`HttpServletRequest#getRemoteUser()`]
|
||||
** https://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#getUserPrincipal()[`HttpServletRequest.html#getUserPrincipal()`]
|
||||
** https://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#isUserInRole(java.lang.String)[`HttpServletRequest.html#isUserInRole(java.lang.String)`]
|
||||
** https://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#login(java.lang.String,%20java.lang.String)[`HttpServletRequest.html#login(java.lang.String, java.lang.String)`]
|
||||
** https://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#logout()[`HttpServletRequest.html#logout()`]
|
||||
|
|
@ -544,7 +544,7 @@ Will output HTML that is similar to the following:
|
|||
=== Resolving the CsrfToken
|
||||
|
||||
Spring Security provides `CsrfTokenArgumentResolver` which can automatically resolve the current `CsrfToken` for Spring MVC arguments.
|
||||
By using xref:servlet/java-configuration/index.adoc#jc-hello-wsca[@EnableWebSecurity] you will automatically have this added to your Spring MVC configuration.
|
||||
By using xref:servlet/java-configuration.adoc#jc-hello-wsca[@EnableWebSecurity] you will automatically have this added to your Spring MVC configuration.
|
||||
If you use XML based configuration, you must add this yourself.
|
||||
|
||||
Once `CsrfTokenArgumentResolver` is properly configured, you can expose the `CsrfToken` to your static HTML based application.
|
||||
|
|
|
@ -0,0 +1,337 @@
|
|||
|
||||
[[jc]]
|
||||
= Java Configuration
|
||||
|
||||
General support for https://docs.spring.io/spring/docs/3.1.x/spring-framework-reference/html/beans.html#beans-java[Java Configuration] was added to Spring Framework in Spring 3.1.
|
||||
Since Spring Security 3.2 there has been Spring Security Java Configuration support which enables users to easily configure Spring Security without the use of any XML.
|
||||
|
||||
If you are familiar with the xref:servlet/xml-namespace.adoc#ns-config[Security Namespace Configuration] then you should find quite a few similarities between it and the Security Java Configuration support.
|
||||
|
||||
NOTE: Spring Security provides https://github.com/spring-projects/spring-security-samples/tree/main/servlet/java-configuration[lots of sample applications] which demonstrate the use of Spring Security Java Configuration.
|
||||
|
||||
== Hello Web Security Java Configuration
|
||||
|
||||
The first step is to create our Spring Security Java Configuration.
|
||||
The configuration creates a Servlet Filter known as the `springSecurityFilterChain` which is responsible for all the security (protecting the application URLs, validating submitted username and passwords, redirecting to the log in form, etc) within your application.
|
||||
You can find the most basic example of a Spring Security Java Configuration below:
|
||||
|
||||
[[jc-hello-wsca]]
|
||||
[source,java]
|
||||
----
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import org.springframework.context.annotation.*;
|
||||
import org.springframework.security.config.annotation.authentication.builders.*;
|
||||
import org.springframework.security.config.annotation.web.configuration.*;
|
||||
|
||||
@EnableWebSecurity
|
||||
public class WebSecurityConfig {
|
||||
|
||||
@Bean
|
||||
public UserDetailsService userDetailsService() {
|
||||
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
|
||||
manager.createUser(User.withDefaultPasswordEncoder().username("user").password("password").roles("USER").build());
|
||||
return manager;
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
There really isn't much to this configuration, but it does a lot.
|
||||
You can find a summary of the features below:
|
||||
|
||||
* Require authentication to every URL in your application
|
||||
* Generate a login form for you
|
||||
* Allow the user with the *Username* _user_ and the *Password* _password_ to authenticate with form based authentication
|
||||
* Allow the user to logout
|
||||
* https://en.wikipedia.org/wiki/Cross-site_request_forgery[CSRF attack] prevention
|
||||
* https://en.wikipedia.org/wiki/Session_fixation[Session Fixation] protection
|
||||
* Security Header integration
|
||||
** https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security[HTTP Strict Transport Security] for secure requests
|
||||
** https://msdn.microsoft.com/en-us/library/ie/gg622941(v=vs.85).aspx[X-Content-Type-Options] integration
|
||||
** Cache Control (can be overridden later by your application to allow caching of your static resources)
|
||||
** https://msdn.microsoft.com/en-us/library/dd565647(v=vs.85).aspx[X-XSS-Protection] integration
|
||||
** X-Frame-Options integration to help prevent https://en.wikipedia.org/wiki/Clickjacking[Clickjacking]
|
||||
* Integrate with the following Servlet API methods
|
||||
** https://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#getRemoteUser()[HttpServletRequest#getRemoteUser()]
|
||||
** https://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#getUserPrincipal()[HttpServletRequest#getUserPrincipal()]
|
||||
** https://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#isUserInRole(java.lang.String)[HttpServletRequest#isUserInRole(java.lang.String)]
|
||||
** https://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#login(java.lang.String,%20java.lang.String)[HttpServletRequest#login(java.lang.String, java.lang.String)]
|
||||
** https://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#logout()[HttpServletRequest#logout()]
|
||||
|
||||
=== AbstractSecurityWebApplicationInitializer
|
||||
|
||||
The next step is to register the `springSecurityFilterChain` with the war.
|
||||
This can be done in Java Configuration with https://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/mvc.html#mvc-container-config[Spring's WebApplicationInitializer support] in a Servlet 3.0+ environment.
|
||||
Not suprisingly, Spring Security provides a base class `AbstractSecurityWebApplicationInitializer` that will ensure the `springSecurityFilterChain` gets registered for you.
|
||||
The way in which we use `AbstractSecurityWebApplicationInitializer` differs depending on if we are already using Spring or if Spring Security is the only Spring component in our application.
|
||||
|
||||
* <<abstractsecuritywebapplicationinitializer-without-existing-spring>> - Use these instructions if you are not using Spring already
|
||||
* <<abstractsecuritywebapplicationinitializer-with-spring-mvc>> - Use these instructions if you are already using Spring
|
||||
|
||||
=== AbstractSecurityWebApplicationInitializer without Existing Spring
|
||||
|
||||
If you are not using Spring or Spring MVC, you will need to pass in the `WebSecurityConfig` into the superclass to ensure the configuration is picked up.
|
||||
You can find an example below:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
import org.springframework.security.web.context.*;
|
||||
|
||||
public class SecurityWebApplicationInitializer
|
||||
extends AbstractSecurityWebApplicationInitializer {
|
||||
|
||||
public SecurityWebApplicationInitializer() {
|
||||
super(WebSecurityConfig.class);
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
The `SecurityWebApplicationInitializer` will do the following things:
|
||||
|
||||
* Automatically register the springSecurityFilterChain Filter for every URL in your application
|
||||
* Add a ContextLoaderListener that loads the <<jc-hello-wsca,WebSecurityConfig>>.
|
||||
|
||||
=== AbstractSecurityWebApplicationInitializer with Spring MVC
|
||||
|
||||
If we were using Spring elsewhere in our application we probably already had a `WebApplicationInitializer` that is loading our Spring Configuration.
|
||||
If we use the previous configuration we would get an error.
|
||||
Instead, we should register Spring Security with the existing `ApplicationContext`.
|
||||
For example, if we were using Spring MVC our `SecurityWebApplicationInitializer` would look something like the following:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
import org.springframework.security.web.context.*;
|
||||
|
||||
public class SecurityWebApplicationInitializer
|
||||
extends AbstractSecurityWebApplicationInitializer {
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
This would simply only register the springSecurityFilterChain Filter for every URL in your application.
|
||||
After that we would ensure that `WebSecurityConfig` was loaded in our existing ApplicationInitializer.
|
||||
For example, if we were using Spring MVC it would be added in the `getRootConfigClasses()`
|
||||
|
||||
[[message-web-application-inititializer-java]]
|
||||
[source,java]
|
||||
----
|
||||
public class MvcWebApplicationInitializer extends
|
||||
AbstractAnnotationConfigDispatcherServletInitializer {
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getRootConfigClasses() {
|
||||
return new Class[] { WebSecurityConfig.class };
|
||||
}
|
||||
|
||||
// ... other overrides ...
|
||||
}
|
||||
----
|
||||
|
||||
[[jc-httpsecurity]]
|
||||
== HttpSecurity
|
||||
|
||||
Thus far our <<jc-hello-wsca,WebSecurityConfig>> only contains information about how to authenticate our users.
|
||||
How does Spring Security know that we want to require all users to be authenticated?
|
||||
How does Spring Security know we want to support form based authentication?
|
||||
Actually, there is a configuration class that is being invoked behind the scenes called `WebSecurityConfigurerAdapter`.
|
||||
It has a method called `configure` with the following default implementation:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeRequests(authorize -> authorize
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.formLogin(withDefaults())
|
||||
.httpBasic(withDefaults());
|
||||
}
|
||||
----
|
||||
|
||||
The default configuration above:
|
||||
|
||||
* Ensures that any request to our application requires the user to be authenticated
|
||||
* Allows users to authenticate with form based login
|
||||
* Allows users to authenticate with HTTP Basic authentication
|
||||
|
||||
You will notice that this configuration is quite similar the XML Namespace configuration:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<http>
|
||||
<intercept-url pattern="/**" access="authenticated"/>
|
||||
<form-login />
|
||||
<http-basic />
|
||||
</http>
|
||||
----
|
||||
|
||||
== Multiple HttpSecurity
|
||||
|
||||
We can configure multiple HttpSecurity instances just as we can have multiple `<http>` blocks.
|
||||
The key is to extend the `WebSecurityConfigurerAdapter` multiple times.
|
||||
For example, the following is an example of having a different configuration for URL's that start with `/api/`.
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@EnableWebSecurity
|
||||
public class MultiHttpSecurityConfig {
|
||||
@Bean <1>
|
||||
public UserDetailsService userDetailsService() throws Exception {
|
||||
// ensure the passwords are encoded properly
|
||||
UserBuilder users = User.withDefaultPasswordEncoder();
|
||||
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
|
||||
manager.createUser(users.username("user").password("password").roles("USER").build());
|
||||
manager.createUser(users.username("admin").password("password").roles("USER","ADMIN").build());
|
||||
return manager;
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Order(1) <2>
|
||||
public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.antMatcher("/api/**") <3>
|
||||
.authorizeRequests(authorize -> authorize
|
||||
.anyRequest().hasRole("ADMIN")
|
||||
)
|
||||
.httpBasic(withDefaults());
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration <4>
|
||||
public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeRequests(authorize -> authorize
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.formLogin(withDefaults());
|
||||
}
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
<1> Configure Authentication as normal
|
||||
<2> Create an instance of `WebSecurityConfigurerAdapter` that contains `@Order` to specify which `WebSecurityConfigurerAdapter` should be considered first.
|
||||
<3> The `http.antMatcher` states that this `HttpSecurity` will only be applicable to URLs that start with `/api/`
|
||||
<4> Create another instance of `WebSecurityConfigurerAdapter`.
|
||||
If the URL does not start with `/api/` this configuration will be used.
|
||||
This configuration is considered after `ApiWebSecurityConfigurationAdapter` since it has an `@Order` value after `1` (no `@Order` defaults to last).
|
||||
|
||||
[[jc-custom-dsls]]
|
||||
== Custom DSLs
|
||||
|
||||
You can provide your own custom DSLs in Spring Security.
|
||||
For example, you might have something that looks like this:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
public class MyCustomDsl extends AbstractHttpConfigurer<MyCustomDsl, HttpSecurity> {
|
||||
private boolean flag;
|
||||
|
||||
@Override
|
||||
public void init(HttpSecurity http) throws Exception {
|
||||
// any method that adds another configurer
|
||||
// must be done in the init method
|
||||
http.csrf().disable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(HttpSecurity http) throws Exception {
|
||||
ApplicationContext context = http.getSharedObject(ApplicationContext.class);
|
||||
|
||||
// here we lookup from the ApplicationContext. You can also just create a new instance.
|
||||
MyFilter myFilter = context.getBean(MyFilter.class);
|
||||
myFilter.setFlag(flag);
|
||||
http.addFilterBefore(myFilter, UsernamePasswordAuthenticationFilter.class);
|
||||
}
|
||||
|
||||
public MyCustomDsl flag(boolean value) {
|
||||
this.flag = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public static MyCustomDsl customDsl() {
|
||||
return new MyCustomDsl();
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
NOTE: This is actually how methods like `HttpSecurity.authorizeRequests()` are implemented.
|
||||
|
||||
The custom DSL can then be used like this:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@EnableWebSecurity
|
||||
public class Config extends WebSecurityConfigurerAdapter {
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.apply(customDsl())
|
||||
.flag(true)
|
||||
.and()
|
||||
...;
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
The code is invoked in the following order:
|
||||
|
||||
* Code in `Config`s configure method is invoked
|
||||
* Code in `MyCustomDsl`s init method is invoked
|
||||
* Code in `MyCustomDsl`s configure method is invoked
|
||||
|
||||
If you want, you can have `WebSecurityConfigurerAdapter` add `MyCustomDsl` by default by using `SpringFactories`.
|
||||
For example, you would create a resource on the classpath named `META-INF/spring.factories` with the following contents:
|
||||
|
||||
.META-INF/spring.factories
|
||||
----
|
||||
org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer = sample.MyCustomDsl
|
||||
----
|
||||
|
||||
Users wishing to disable the default can do so explicitly.
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@EnableWebSecurity
|
||||
public class Config extends WebSecurityConfigurerAdapter {
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.apply(customDsl()).disable()
|
||||
...;
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
[[post-processing-configured-objects]]
|
||||
== Post Processing Configured Objects
|
||||
|
||||
Spring Security's Java Configuration does not expose every property of every object that it configures.
|
||||
This simplifies the configuration for a majority of users.
|
||||
Afterall, if every property was exposed, users could use standard bean configuration.
|
||||
|
||||
While there are good reasons to not directly expose every property, users may still need more advanced configuration options.
|
||||
To address this Spring Security introduces the concept of an `ObjectPostProcessor` which can be used to modify or replace many of the Object instances created by the Java Configuration.
|
||||
For example, if you wanted to configure the `filterSecurityPublishAuthorizationSuccess` property on `FilterSecurityInterceptor` you could use the following:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeRequests(authorize -> authorize
|
||||
.anyRequest().authenticated()
|
||||
.withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
|
||||
public <O extends FilterSecurityInterceptor> O postProcess(
|
||||
O fsi) {
|
||||
fsi.setPublishAuthorizationSuccess(true);
|
||||
return fsi;
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
----
|
|
@ -0,0 +1,99 @@
|
|||
|
||||
[[kotlin-config]]
|
||||
= Kotlin Configuration
|
||||
Spring Security Kotlin Configuration support has been available since Spring Security 5.3.
|
||||
It enables users to easily configure Spring Security using a native Kotlin DSL.
|
||||
|
||||
NOTE: Spring Security provides https://github.com/spring-projects/spring-security-samples/tree/main/servlet/spring-boot/kotlin/hello-security[a sample application] which demonstrates the use of Spring Security Kotlin Configuration.
|
||||
|
||||
[[kotlin-config-httpsecurity]]
|
||||
== HttpSecurity
|
||||
|
||||
How does Spring Security know that we want to require all users to be authenticated?
|
||||
How does Spring Security know we want to support form based authentication?
|
||||
There is a configuration class that is being invoked behind the scenes called `WebSecurityConfigurerAdapter`.
|
||||
It has a method called `configure` with the following default implementation:
|
||||
|
||||
[source,kotlin]
|
||||
----
|
||||
fun configure(http: HttpSecurity) {
|
||||
http {
|
||||
authorizeRequests {
|
||||
authorize(anyRequest, authenticated)
|
||||
}
|
||||
formLogin { }
|
||||
httpBasic { }
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
The default configuration above:
|
||||
|
||||
* Ensures that any request to our application requires the user to be authenticated
|
||||
* Allows users to authenticate with form based login
|
||||
* Allows users to authenticate with HTTP Basic authentication
|
||||
|
||||
You will notice that this configuration is quite similar the XML Namespace configuration:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<http>
|
||||
<intercept-url pattern="/**" access="authenticated"/>
|
||||
<form-login />
|
||||
<http-basic />
|
||||
</http>
|
||||
----
|
||||
|
||||
== Multiple HttpSecurity
|
||||
|
||||
We can configure multiple HttpSecurity instances just as we can have multiple `<http>` blocks.
|
||||
The key is to extend the `WebSecurityConfigurerAdapter` multiple times.
|
||||
For example, the following is an example of having a different configuration for URL's that start with `/api/`.
|
||||
|
||||
[source,kotlin]
|
||||
----
|
||||
@EnableWebSecurity
|
||||
class MultiHttpSecurityConfig {
|
||||
@Bean <1>
|
||||
public fun userDetailsService(): UserDetailsService {
|
||||
val users: User.UserBuilder = User.withDefaultPasswordEncoder()
|
||||
val manager = InMemoryUserDetailsManager()
|
||||
manager.createUser(users.username("user").password("password").roles("USER").build())
|
||||
manager.createUser(users.username("admin").password("password").roles("USER","ADMIN").build())
|
||||
return manager
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Order(1) <2>
|
||||
class ApiWebSecurityConfigurationAdapter: WebSecurityConfigurerAdapter() {
|
||||
override fun configure(http: HttpSecurity) {
|
||||
http {
|
||||
securityMatcher("/api/**") <3>
|
||||
authorizeRequests {
|
||||
authorize(anyRequest, hasRole("ADMIN"))
|
||||
}
|
||||
httpBasic { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration <4>
|
||||
class FormLoginWebSecurityConfigurerAdapter: WebSecurityConfigurerAdapter() {
|
||||
override fun configure(http: HttpSecurity) {
|
||||
http {
|
||||
authorizeRequests {
|
||||
authorize(anyRequest, authenticated)
|
||||
}
|
||||
formLogin { }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
<1> Configure Authentication as normal
|
||||
<2> Create an instance of `WebSecurityConfigurerAdapter` that contains `@Order` to specify which `WebSecurityConfigurerAdapter` should be considered first.
|
||||
<3> The `http.antMatcher` states that this `HttpSecurity` will only be applicable to URLs that start with `/api/`
|
||||
<4> Create another instance of `WebSecurityConfigurerAdapter`.
|
||||
If the URL does not start with `/api/` this configuration will be used.
|
||||
This configuration is considered after `ApiWebSecurityConfigurationAdapter` since it has an `@Order` value after `1` (no `@Order` defaults to last).
|
|
@ -23,13 +23,13 @@ First, we see that, like xref:servlet/authentication/unpwd/basic.adoc#servlet-au
|
|||
.Sending WWW-Authenticate Header
|
||||
image::{figures}/bearerauthenticationentrypoint.png[]
|
||||
|
||||
The figure above builds off our xref:servlet/architecture/index.adoc#servlet-securityfilterchain[`SecurityFilterChain`] diagram.
|
||||
The figure above builds off our xref:servlet/architecture.adoc#servlet-securityfilterchain[`SecurityFilterChain`] diagram.
|
||||
|
||||
image:{icondir}/number_1.png[] First, a user makes an unauthenticated request to the resource `/private` for which it is not authorized.
|
||||
|
||||
image:{icondir}/number_2.png[] Spring Security's xref:servlet/authorization/authorize-requests.adoc#servlet-authorization-filtersecurityinterceptor[`FilterSecurityInterceptor`] indicates that the unauthenticated request is __Denied__ by throwing an `AccessDeniedException`.
|
||||
|
||||
image:{icondir}/number_3.png[] Since the user is not authenticated, xref:servlet/architecture/index.adoc#servlet-exceptiontranslationfilter[`ExceptionTranslationFilter`] initiates __Start Authentication__.
|
||||
image:{icondir}/number_3.png[] Since the user is not authenticated, xref:servlet/architecture.adoc#servlet-exceptiontranslationfilter[`ExceptionTranslationFilter`] initiates __Start Authentication__.
|
||||
The configured xref:servlet/authentication/architecture/index.adoc#servlet-authentication-authenticationentrypoint[`AuthenticationEntryPoint`] is an instance of {security-api-url}org/springframework/security/oauth2/server/resource/web/BearerTokenAuthenticationEntryPoint.html[`BearerTokenAuthenticationEntryPoint`] which sends a WWW-Authenticate header.
|
||||
The `RequestCache` is typically a `NullRequestCache` that does not save the request since the client is capable of replaying the requests it originally requested.
|
||||
|
||||
|
@ -40,7 +40,7 @@ Below is the flow for the bearer token being processed.
|
|||
.Authenticating Bearer Token
|
||||
image::{figures}/bearertokenauthenticationfilter.png[]
|
||||
|
||||
The figure builds off our xref:servlet/architecture/index.adoc#servlet-securityfilterchain[`SecurityFilterChain`] diagram.
|
||||
The figure builds off our xref:servlet/architecture.adoc#servlet-securityfilterchain[`SecurityFilterChain`] diagram.
|
||||
|
||||
image:{icondir}/number_1.png[] When the user submits their bearer token, the `BearerTokenAuthenticationFilter` creates a `BearerTokenAuthenticationToken` which is a type of xref:servlet/authentication/architecture/index.adoc#servlet-authentication-authentication[`Authentication`] by extracting the token from the `HttpServletRequest`.
|
||||
|
||||
|
|
|
@ -30,13 +30,13 @@ It does this through a series of redirects.
|
|||
.Redirecting to Asserting Party Authentication
|
||||
image::{figures}/saml2webssoauthenticationrequestfilter.png[]
|
||||
|
||||
The figure above builds off our xref:servlet/architecture/index.adoc#servlet-securityfilterchain[`SecurityFilterChain`] and xref:servlet/authentication/architecture/index.adoc#servlet-authentication-abstractprocessingfilter[ `AbstractAuthenticationProcessingFilter`] diagrams:
|
||||
The figure above builds off our xref:servlet/architecture.adoc#servlet-securityfilterchain[`SecurityFilterChain`] and xref:servlet/authentication/architecture/index.adoc#servlet-authentication-abstractprocessingfilter[ `AbstractAuthenticationProcessingFilter`] diagrams:
|
||||
|
||||
image:{icondir}/number_1.png[] First, a user makes an unauthenticated request to the resource `/private` for which it is not authorized.
|
||||
|
||||
image:{icondir}/number_2.png[] Spring Security's xref:servlet/authorization/authorize-requests.adoc#servlet-authorization-filtersecurityinterceptor[`FilterSecurityInterceptor`] indicates that the unauthenticated request is __Denied__ by throwing an `AccessDeniedException`.
|
||||
|
||||
image:{icondir}/number_3.png[] Since the user lacks authorization, the xref:servlet/architecture/index.adoc#servlet-exceptiontranslationfilter[`ExceptionTranslationFilter`] initiates __Start Authentication__.
|
||||
image:{icondir}/number_3.png[] Since the user lacks authorization, the xref:servlet/architecture.adoc#servlet-exceptiontranslationfilter[`ExceptionTranslationFilter`] initiates __Start Authentication__.
|
||||
The configured xref:servlet/authentication/architecture/index.adoc#servlet-authentication-authenticationentrypoint[`AuthenticationEntryPoint`] is an instance of {security-api-url}org/springframework/security/web/authentication/LoginUrlAuthenticationEntryPoint.html[`LoginUrlAuthenticationEntryPoint`] which redirects to <<servlet-saml2login-sp-initiated-factory,the `<saml2:AuthnRequest>` generating endpoint>>, `Saml2WebSsoAuthenticationRequestFilter`.
|
||||
Or, if you've <<servlet-saml2login-relyingpartyregistrationrepository,configured more than one asserting party>>, it will first redirect to a picker page.
|
||||
|
||||
|
@ -52,7 +52,7 @@ image:{icondir}/number_6.png[] The browser then POSTs the `<saml2:Response>` to
|
|||
.Authenticating a `<saml2:Response>`
|
||||
image::{figures}/saml2webssoauthenticationfilter.png[]
|
||||
|
||||
The figure builds off our xref:servlet/architecture/index.adoc#servlet-securityfilterchain[`SecurityFilterChain`] diagram.
|
||||
The figure builds off our xref:servlet/architecture.adoc#servlet-securityfilterchain[`SecurityFilterChain`] diagram.
|
||||
|
||||
image:{icondir}/number_1.png[] When the browser submits a `<saml2:Response>` to the application, it <<servlet-saml2login-authenticate-responses, delegates to `Saml2WebSsoAuthenticationFilter`>>.
|
||||
This filter calls its configured `AuthenticationConverter` to create a `Saml2AuthenticationToken` by extracting the response from the `HttpServletRequest`.
|
||||
|
|
|
@ -0,0 +1,402 @@
|
|||
|
||||
[[ns-config]]
|
||||
= Security Namespace Configuration
|
||||
|
||||
|
||||
== Introduction
|
||||
Namespace configuration has been available since version 2.0 of the Spring Framework.
|
||||
It allows you to supplement the traditional Spring beans application context syntax with elements from additional XML schema.
|
||||
You can find more information in the Spring https://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/[Reference Documentation].
|
||||
A namespace element can be used simply to allow a more concise way of configuring an individual bean or, more powerfully, to define an alternative configuration syntax which more closely matches the problem domain and hides the underlying complexity from the user.
|
||||
A simple element may conceal the fact that multiple beans and processing steps are being added to the application context.
|
||||
For example, adding the following element from the security namespace to an application context will start up an embedded LDAP server for testing use within the application:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<security:ldap-server />
|
||||
----
|
||||
|
||||
This is much simpler than wiring up the equivalent Apache Directory Server beans.
|
||||
The most common alternative configuration requirements are supported by attributes on the `ldap-server` element and the user is isolated from worrying about which beans they need to create and what the bean property names are.
|
||||
footnote:[You can find out more about the use of the `ldap-server` element in the chapter on pass:specialcharacters,macros[xref:servlet/authentication/unpwd/ldap.adoc#servlet-authentication-ldap[LDAP Authentication]].].
|
||||
Use of a good XML editor while editing the application context file should provide information on the attributes and elements that are available.
|
||||
We would recommend that you try out the https://spring.io/tools[Eclipse IDE with Spring Tools] as it has special features for working with standard Spring namespaces.
|
||||
|
||||
|
||||
To start using the security namespace in your application context, you need to have the `spring-security-config` jar on your classpath.
|
||||
Then all you need to do is add the schema declaration to your application context file:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:security="http://www.springframework.org/schema/security"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
https://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/security
|
||||
https://www.springframework.org/schema/security/spring-security.xsd">
|
||||
...
|
||||
</beans>
|
||||
----
|
||||
|
||||
In many of the examples you will see (and in the sample applications), we will often use "security" as the default namespace rather than "beans", which means we can omit the prefix on all the security namespace elements, making the content easier to read.
|
||||
You may also want to do this if you have your application context divided up into separate files and have most of your security configuration in one of them.
|
||||
Your security application context file would then start like this
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<beans:beans xmlns="http://www.springframework.org/schema/security"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
https://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/security
|
||||
https://www.springframework.org/schema/security/spring-security.xsd">
|
||||
...
|
||||
</beans:beans>
|
||||
----
|
||||
|
||||
We'll assume this syntax is being used from now on in this chapter.
|
||||
|
||||
|
||||
=== Design of the Namespace
|
||||
The namespace is designed to capture the most common uses of the framework and provide a simplified and concise syntax for enabling them within an application.
|
||||
The design is based around the large-scale dependencies within the framework, and can be divided up into the following areas:
|
||||
|
||||
* __Web/HTTP Security__ - the most complex part.
|
||||
Sets up the filters and related service beans used to apply the framework authentication mechanisms, to secure URLs, render login and error pages and much more.
|
||||
|
||||
* __Business Object (Method) Security__ - options for securing the service layer.
|
||||
|
||||
* __AuthenticationManager__ - handles authentication requests from other parts of the framework.
|
||||
|
||||
* __AccessDecisionManager__ - provides access decisions for web and method security.
|
||||
A default one will be registered, but you can also choose to use a custom one, declared using normal Spring bean syntax.
|
||||
|
||||
* __AuthenticationProvider__s - mechanisms against which the authentication manager authenticates users.
|
||||
The namespace provides supports for several standard options and also a means of adding custom beans declared using a traditional syntax.
|
||||
|
||||
* __UserDetailsService__ - closely related to authentication providers, but often also required by other beans.
|
||||
|
||||
We'll see how to configure these in the following sections.
|
||||
|
||||
[[ns-getting-started]]
|
||||
== Getting Started with Security Namespace Configuration
|
||||
In this section, we'll look at how you can build up a namespace configuration to use some of the main features of the framework.
|
||||
Let's assume you initially want to get up and running as quickly as possible and add authentication support and access control to an existing web application, with a few test logins.
|
||||
Then we'll look at how to change over to authenticating against a database or other security repository.
|
||||
In later sections we'll introduce more advanced namespace configuration options.
|
||||
|
||||
[[ns-web-xml]]
|
||||
=== web.xml Configuration
|
||||
The first thing you need to do is add the following filter declaration to your `web.xml` file:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<filter>
|
||||
<filter-name>springSecurityFilterChain</filter-name>
|
||||
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
|
||||
</filter>
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>springSecurityFilterChain</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
----
|
||||
|
||||
This provides a hook into the Spring Security web infrastructure.
|
||||
`DelegatingFilterProxy` is a Spring Framework class which delegates to a filter implementation which is defined as a Spring bean in your application context.
|
||||
In this case, the bean is named "springSecurityFilterChain", which is an internal infrastructure bean created by the namespace to handle web security.
|
||||
Note that you should not use this bean name yourself.
|
||||
Once you've added this to your `web.xml`, you're ready to start editing your application context file.
|
||||
Web security services are configured using the `<http>` element.
|
||||
|
||||
[[ns-minimal]]
|
||||
=== A Minimal <http> Configuration
|
||||
All you need to enable web security to begin with is
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<http>
|
||||
<intercept-url pattern="/**" access="hasRole('USER')" />
|
||||
<form-login />
|
||||
<logout />
|
||||
</http>
|
||||
----
|
||||
|
||||
Which says that we want all URLs within our application to be secured, requiring the role `ROLE_USER` to access them, we want to log in to the application using a form with username and password, and that we want a logout URL registered which will allow us to log out of the application.
|
||||
`<http>` element is the parent for all web-related namespace functionality.
|
||||
The `<intercept-url>` element defines a `pattern` which is matched against the URLs of incoming requests using an ant path style syntax footnote:[See the section on pass:specialcharacters,macros[xref:servlet/exploits/firewall.adoc#servlet-httpfirewall[`HttpFirewall`]] for more details on how matches are actually performed.].
|
||||
You can also use regular-expression matching as an alternative (see the namespace appendix for more details).
|
||||
The `access` attribute defines the access requirements for requests matching the given pattern.
|
||||
With the default configuration, this is typically a comma-separated list of roles, one of which a user must have to be allowed to make the request.
|
||||
The prefix "ROLE_" is a marker which indicates that a simple comparison with the user's authorities should be made.
|
||||
In other words, a normal role-based check should be used.
|
||||
Access-control in Spring Security is not limited to the use of simple roles (hence the use of the prefix to differentiate between different types of security attributes).
|
||||
We'll see later how the interpretation can vary footnote:[The interpretation of the comma-separated values in the `access` attribute depends on the implementation of the <<ns-access-manager,AccessDecisionManager>> which is used.].
|
||||
In Spring Security 3.0, the attribute can also be populated with an xref:servlet/authorization/expression-based.adoc#el-access[EL expression].
|
||||
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
|
||||
You can use multiple `<intercept-url>` elements to define different access requirements for different sets of URLs, but they will be evaluated in the order listed and the first match will be used.
|
||||
So you must put the most specific matches at the top.
|
||||
You can also add a `method` attribute to limit the match to a particular HTTP method (`GET`, `POST`, `PUT` etc.).
|
||||
|
||||
====
|
||||
|
||||
To add some users, you can define a set of test data directly in the namespace:
|
||||
|
||||
[source,xml,attrs="-attributes"]
|
||||
----
|
||||
<authentication-manager>
|
||||
<authentication-provider>
|
||||
<user-service>
|
||||
<!-- Password is prefixed with {noop} to indicate to DelegatingPasswordEncoder that
|
||||
NoOpPasswordEncoder should be used. This is not safe for production, but makes reading
|
||||
in samples easier. Normally passwords should be hashed using BCrypt -->
|
||||
<user name="jimi" password="{noop}jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
|
||||
<user name="bob" password="{noop}bobspassword" authorities="ROLE_USER" />
|
||||
</user-service>
|
||||
</authentication-provider>
|
||||
</authentication-manager>
|
||||
----
|
||||
|
||||
This is an example of a secure way of storing the same passwords.
|
||||
The password is prefixed with `+{bcrypt}+` to instruct `DelegatingPasswordEncoder`, which supports any configured `PasswordEncoder` for matching, that the passwords are hashed using BCrypt:
|
||||
|
||||
[source,xml,attrs="-attributes"]
|
||||
----
|
||||
<authentication-manager>
|
||||
<authentication-provider>
|
||||
<user-service>
|
||||
<user name="jimi" password="{bcrypt}$2a$10$ddEWZUl8aU0GdZPPpy7wbu82dvEw/pBpbRvDQRqA41y6mK1CoH00m"
|
||||
authorities="ROLE_USER, ROLE_ADMIN" />
|
||||
<user name="bob" password="{bcrypt}$2a$10$/elFpMBnAYYig6KRR5bvOOYeZr1ie1hSogJryg9qDlhza4oCw1Qka"
|
||||
authorities="ROLE_USER" />
|
||||
<user name="jimi" password="{noop}jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
|
||||
<user name="bob" password="{noop}bobspassword" authorities="ROLE_USER" />
|
||||
</user-service>
|
||||
</authentication-provider>
|
||||
</authentication-manager>
|
||||
----
|
||||
|
||||
|
||||
|
||||
[subs="quotes"]
|
||||
****
|
||||
If you are familiar with pre-namespace versions of the framework, you can probably already guess roughly what's going on here.
|
||||
The `<http>` element is responsible for creating a `FilterChainProxy` and the filter beans which it uses.
|
||||
Common problems like incorrect filter ordering are no longer an issue as the filter positions are predefined.
|
||||
|
||||
The `<authentication-provider>` element creates a `DaoAuthenticationProvider` bean and the `<user-service>` element creates an `InMemoryDaoImpl`.
|
||||
All `authentication-provider` elements must be children of the `<authentication-manager>` element, which creates a `ProviderManager` and registers the authentication providers with it.
|
||||
You can find more detailed information on the beans that are created in the xref:servlet/appendix/namespace.adoc#appendix-namespace[namespace appendix].
|
||||
It's worth cross-checking this if you want to start understanding what the important classes in the framework are and how they are used, particularly if you want to customise things later.
|
||||
****
|
||||
|
||||
The configuration above defines two users, their passwords and their roles within the application (which will be used for access control).
|
||||
It is also possible to load user information from a standard properties file using the `properties` attribute on `user-service`.
|
||||
See the section on xref:servlet/authentication/unpwd/in-memory.adoc#servlet-authentication-inmemory[in-memory authentication] for more details on the file format.
|
||||
Using the `<authentication-provider>` element means that the user information will be used by the authentication manager to process authentication requests.
|
||||
You can have multiple `<authentication-provider>` elements to define different authentication sources and each will be consulted in turn.
|
||||
|
||||
At this point you should be able to start up your application and you will be required to log in to proceed.
|
||||
Try it out, or try experimenting with the "tutorial" sample application that comes with the project.
|
||||
|
||||
[[ns-form-target]]
|
||||
==== Setting a Default Post-Login Destination
|
||||
If a form login isn't prompted by an attempt to access a protected resource, the `default-target-url` option comes into play.
|
||||
This is the URL the user will be taken to after successfully logging in, and defaults to "/".
|
||||
You can also configure things so that the user __always__ ends up at this page (regardless of whether the login was "on-demand" or they explicitly chose to log in) by setting the `always-use-default-target` attribute to "true".
|
||||
This is useful if your application always requires that the user starts at a "home" page, for example:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<http pattern="/login.htm*" security="none"/>
|
||||
<http use-expressions="false">
|
||||
<intercept-url pattern='/**' access='ROLE_USER' />
|
||||
<form-login login-page='/login.htm' default-target-url='/home.htm'
|
||||
always-use-default-target='true' />
|
||||
</http>
|
||||
----
|
||||
|
||||
For even more control over the destination, you can use the `authentication-success-handler-ref` attribute as an alternative to `default-target-url`.
|
||||
The referenced bean should be an instance of `AuthenticationSuccessHandler`.
|
||||
|
||||
[[ns-web-advanced]]
|
||||
== Advanced Web Features
|
||||
|
||||
[[ns-custom-filters]]
|
||||
=== Adding in Your Own Filters
|
||||
If you've used Spring Security before, you'll know that the framework maintains a chain of filters in order to apply its services.
|
||||
You may want to add your own filters to the stack at particular locations or use a Spring Security filter for which there isn't currently a namespace configuration option (CAS, for example).
|
||||
Or you might want to use a customized version of a standard namespace filter, such as the `UsernamePasswordAuthenticationFilter` which is created by the `<form-login>` element, taking advantage of some of the extra configuration options which are available by using the bean explicitly.
|
||||
How can you do this with namespace configuration, since the filter chain is not directly exposed?
|
||||
|
||||
The order of the filters is always strictly enforced when using the namespace.
|
||||
When the application context is being created, the filter beans are sorted by the namespace handling code and the standard Spring Security filters each have an alias in the namespace and a well-known position.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
In previous versions, the sorting took place after the filter instances had been created, during post-processing of the application context.
|
||||
In version 3.0+ the sorting is now done at the bean metadata level, before the classes have been instantiated.
|
||||
This has implications for how you add your own filters to the stack as the entire filter list must be known during the parsing of the `<http>` element, so the syntax has changed slightly in 3.0.
|
||||
====
|
||||
|
||||
The filters, aliases and namespace elements/attributes which create the filters are shown in <<filter-stack>>.
|
||||
The filters are listed in the order in which they occur in the filter chain.
|
||||
|
||||
[[filter-stack]]
|
||||
.Standard Filter Aliases and Ordering
|
||||
|===
|
||||
| Alias | Filter Class | Namespace Element or Attribute
|
||||
|
||||
| CHANNEL_FILTER
|
||||
| `ChannelProcessingFilter`
|
||||
| `http/intercept-url@requires-channel`
|
||||
|
||||
| SECURITY_CONTEXT_FILTER
|
||||
| `SecurityContextPersistenceFilter`
|
||||
| `http`
|
||||
|
||||
| CONCURRENT_SESSION_FILTER
|
||||
| `ConcurrentSessionFilter`
|
||||
| `session-management/concurrency-control`
|
||||
|
||||
| HEADERS_FILTER
|
||||
| `HeaderWriterFilter`
|
||||
| `http/headers`
|
||||
|
||||
| CSRF_FILTER
|
||||
| `CsrfFilter`
|
||||
| `http/csrf`
|
||||
|
||||
| LOGOUT_FILTER
|
||||
| `LogoutFilter`
|
||||
| `http/logout`
|
||||
|
||||
| X509_FILTER
|
||||
| `X509AuthenticationFilter`
|
||||
| `http/x509`
|
||||
|
||||
| PRE_AUTH_FILTER
|
||||
| `AbstractPreAuthenticatedProcessingFilter` Subclasses
|
||||
| N/A
|
||||
|
||||
| CAS_FILTER
|
||||
| `CasAuthenticationFilter`
|
||||
| N/A
|
||||
|
||||
| FORM_LOGIN_FILTER
|
||||
| `UsernamePasswordAuthenticationFilter`
|
||||
| `http/form-login`
|
||||
|
||||
| BASIC_AUTH_FILTER
|
||||
| `BasicAuthenticationFilter`
|
||||
| `http/http-basic`
|
||||
|
||||
| SERVLET_API_SUPPORT_FILTER
|
||||
| `SecurityContextHolderAwareRequestFilter`
|
||||
| `http/@servlet-api-provision`
|
||||
|
||||
| JAAS_API_SUPPORT_FILTER
|
||||
| `JaasApiIntegrationFilter`
|
||||
| `http/@jaas-api-provision`
|
||||
|
||||
| REMEMBER_ME_FILTER
|
||||
| `RememberMeAuthenticationFilter`
|
||||
| `http/remember-me`
|
||||
|
||||
| ANONYMOUS_FILTER
|
||||
| `AnonymousAuthenticationFilter`
|
||||
| `http/anonymous`
|
||||
|
||||
| SESSION_MANAGEMENT_FILTER
|
||||
| `SessionManagementFilter`
|
||||
| `session-management`
|
||||
|
||||
| EXCEPTION_TRANSLATION_FILTER
|
||||
| `ExceptionTranslationFilter`
|
||||
| `http`
|
||||
|
||||
| FILTER_SECURITY_INTERCEPTOR
|
||||
| `FilterSecurityInterceptor`
|
||||
| `http`
|
||||
|
||||
| SWITCH_USER_FILTER
|
||||
| `SwitchUserFilter`
|
||||
| N/A
|
||||
|===
|
||||
|
||||
You can add your own filter to the stack, using the `custom-filter` element and one of these names to specify the position your filter should appear at:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<http>
|
||||
<custom-filter position="FORM_LOGIN_FILTER" ref="myFilter" />
|
||||
</http>
|
||||
|
||||
<beans:bean id="myFilter" class="com.mycompany.MySpecialAuthenticationFilter"/>
|
||||
----
|
||||
|
||||
You can also use the `after` or `before` attributes if you want your filter to be inserted before or after another filter in the stack.
|
||||
The names "FIRST" and "LAST" can be used with the `position` attribute to indicate that you want your filter to appear before or after the entire stack, respectively.
|
||||
|
||||
.Avoiding filter position conflicts
|
||||
[TIP]
|
||||
====
|
||||
|
||||
If you are inserting a custom filter which may occupy the same position as one of the standard filters created by the namespace then it's important that you don't include the namespace versions by mistake.
|
||||
Remove any elements which create filters whose functionality you want to replace.
|
||||
|
||||
Note that you can't replace filters which are created by the use of the `<http>` element itself - `SecurityContextPersistenceFilter`, `ExceptionTranslationFilter` or `FilterSecurityInterceptor`.
|
||||
Some other filters are added by default, but you can disable them.
|
||||
An `AnonymousAuthenticationFilter` is added by default and unless you have xref:servlet/authentication/session-management.adoc#ns-session-fixation[session-fixation protection] disabled, a `SessionManagementFilter` will also be added to the filter chain.
|
||||
|
||||
====
|
||||
|
||||
If you're replacing a namespace filter which requires an authentication entry point (i.e. where the authentication process is triggered by an attempt by an unauthenticated user to access to a secured resource), you will need to add a custom entry point bean too.
|
||||
|
||||
|
||||
|
||||
[[ns-method-security]]
|
||||
== Method Security
|
||||
From version 2.0 onwards Spring Security has improved support substantially for adding security to your service layer methods.
|
||||
It provides support for JSR-250 annotation security as well as the framework's original `@Secured` annotation.
|
||||
From 3.0 you can also make use of new xref:servlet/authorization/expression-based.adoc#el-access[expression-based annotations].
|
||||
You can apply security to a single bean, using the `intercept-methods` element to decorate the bean declaration, or you can secure multiple beans across the entire service layer using the AspectJ style pointcuts.
|
||||
|
||||
[[ns-access-manager]]
|
||||
== The Default AccessDecisionManager
|
||||
This section assumes you have some knowledge of the underlying architecture for access-control within Spring Security.
|
||||
If you don't you can skip it and come back to it later, as this section is only really relevant for people who need to do some customization in order to use more than simple role-based security.
|
||||
|
||||
When you use a namespace configuration, a default instance of `AccessDecisionManager` is automatically registered for you and will be used for making access decisions for method invocations and web URL access, based on the access attributes you specify in your `intercept-url` and `protect-pointcut` declarations (and in annotations if you are using annotation secured methods).
|
||||
|
||||
The default strategy is to use an `AffirmativeBased` `AccessDecisionManager` with a `RoleVoter` and an `AuthenticatedVoter`.
|
||||
You can find out more about these in the chapter on xref:servlet/authorization/architecture.adoc#authz-arch[authorization].
|
||||
|
||||
|
||||
[[ns-custom-access-mgr]]
|
||||
=== Customizing the AccessDecisionManager
|
||||
If you need to use a more complicated access control strategy then it is easy to set an alternative for both method and web security.
|
||||
|
||||
For method security, you do this by setting the `access-decision-manager-ref` attribute on `global-method-security` to the `id` of the appropriate `AccessDecisionManager` bean in the application context:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<global-method-security access-decision-manager-ref="myAccessDecisionManagerBean">
|
||||
...
|
||||
</global-method-security>
|
||||
----
|
||||
|
||||
The syntax for web security is the same, but on the `http` element:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<http access-decision-manager-ref="myAccessDecisionManagerBean">
|
||||
...
|
||||
</http>
|
||||
----
|
Loading…
Reference in New Issue