Add ProviderManager to Reference

Closes gh-8029
This commit is contained in:
Rob Winch 2020-02-24 15:13:41 -06:00
parent bd593a3431
commit d009a7b1de
14 changed files with 53 additions and 67 deletions

View File

@ -2039,8 +2039,7 @@ Its use is described in the <<ns-auth-manager,namespace introduction>>.
[[nsa-authentication-manager-erase-credentials]]
* **erase-credentials**
If set to true, the AuthenticationManager will attempt to clear any credentials data in the returned Authentication object, once the user has been authenticated.
Literally it maps to the `eraseCredentialsAfterAuthentication` property of the `ProviderManager`.
This is discussed in the <<core-services-erasing-credentials,Core Services>> chapter.
Literally it maps to the `eraseCredentialsAfterAuthentication` property of the <<servlet-authentication-providermanager,`ProviderManager`>>.
[[nsa-authentication-manager-id]]

View File

@ -3,65 +3,8 @@
Now that we have a high-level overview of the Spring Security architecture and its core classes, let's take a closer look at one or two of the core interfaces and their implementations, in particular the `AuthenticationManager`, `UserDetailsService` and the `AccessDecisionManager`.
These crop up regularly throughout the remainder of this document so it's important you know how they are configured and how they operate.
[[core-services-authentication-manager]]
=== The AuthenticationManager, ProviderManager and AuthenticationProvider
The `AuthenticationManager` is just an interface, so the implementation can be anything we choose, but how does it work in practice? What if we need to check multiple authentication databases or a combination of different authentication services such as a database and an LDAP server?
The default implementation in Spring Security is called `ProviderManager` and rather than handling the authentication request itself, it delegates to a list of configured `AuthenticationProvider` s, each of which is queried in turn to see if it can perform the authentication.
Each provider will either throw an exception or return a fully populated `Authentication` object.
Remember our good friends, `UserDetails` and `UserDetailsService`? If not, head back to the previous chapter and refresh your memory.
The most common approach to verifying an authentication request is to load the corresponding `UserDetails` and check the loaded password against the one that has been entered by the user.
This is the approach used by the `DaoAuthenticationProvider` (see below).
The loaded `UserDetails` object - and particularly the `GrantedAuthority` s it contains - will be used when building the fully populated `Authentication` object which is returned from a successful authentication and stored in the `SecurityContext`.
If you are using the namespace, an instance of `ProviderManager` is created and maintained internally, and you add providers to it by using the namespace authentication provider elements (see <<ns-auth-manager,the namespace chapter>>).
In this case, you should not declare a `ProviderManager` bean in your application context.
However, if you are not using the namespace then you would declare it like so:
[source,xml]
----
<bean id="authenticationManager"
class="org.springframework.security.authentication.ProviderManager">
<constructor-arg>
<list>
<ref local="daoAuthenticationProvider"/>
<ref local="anonymousAuthenticationProvider"/>
<ref local="ldapAuthenticationProvider"/>
</list>
</constructor-arg>
</bean>
----
In the above example we have three providers.
They are tried in the order shown (which is implied by the use of a `List`), with each provider able to attempt authentication, or skip authentication by simply returning `null`.
If all implementations return null, the `ProviderManager` will throw a `ProviderNotFoundException`.
If you're interested in learning more about chaining providers, please refer to the `ProviderManager` Javadoc.
Authentication mechanisms such as a web form-login processing filter are injected with a reference to the `ProviderManager` and will call it to handle their authentication requests.
The providers you require will sometimes be interchangeable with the authentication mechanisms, while at other times they will depend on a specific authentication mechanism.
For example, `DaoAuthenticationProvider` and `LdapAuthenticationProvider` are compatible with any mechanism which submits a simple username/password authentication request and so will work with form-based logins or HTTP Basic authentication.
On the other hand, some authentication mechanisms create an authentication request object which can only be interpreted by a single type of `AuthenticationProvider`.
An example of this would be JA-SIG CAS, which uses the notion of a service ticket and so can therefore only be authenticated by a `CasAuthenticationProvider`.
You needn't be too concerned about this, because if you forget to register a suitable provider, you'll simply receive a `ProviderNotFoundException` when an attempt to authenticate is made.
[[core-services-erasing-credentials]]
==== Erasing Credentials on Successful Authentication
By default (from Spring Security 3.1 onwards) the `ProviderManager` will attempt to clear any sensitive credentials information from the `Authentication` object which is returned by a successful authentication request.
This prevents information like passwords being retained longer than necessary.
This may cause issues when you are using a cache of user objects, for example, to improve performance in a stateless application.
If the `Authentication` contains a reference to an object in the cache (such as a `UserDetails` instance) and this has its credentials removed, then it will no longer be possible to authenticate against the cached value.
You need to take this into account if you are using a cache.
An obvious solution is to make a copy of the object first, either in the cache implementation or in the `AuthenticationProvider` which creates the returned `Authentication` object.
Alternatively, you can disable the `eraseCredentialsAfterAuthentication` property on `ProviderManager`.
See the Javadoc for more information.
[[core-services-dao-provider]]
==== DaoAuthenticationProvider
=== DaoAuthenticationProvider
The simplest `AuthenticationProvider` implemented by Spring Security is `DaoAuthenticationProvider`, which is also one of the earliest supported by the framework.
It leverages a `UserDetailsService` (as a DAO) in order to lookup the username, password and `GrantedAuthority` s.
It authenticates the user simply by comparing the password submitted in a `UsernamePasswordAuthenticationToken` against the one loaded by the `UserDetailsService`.

View File

@ -1,5 +1,6 @@
[[servlet-architecture]]
= Architecture and Implementation
// FIXME: change to something like Servlet Security: The Big Picture
:figures: images/servlet/architecture
This section discusses Spring Security's high level architecture within Servlet based applications.

View File

@ -42,7 +42,7 @@ Remember the advantage that whatever your `UserDetailsService` returns can alway
There is often some confusion about `UserDetailsService`.
It is purely a DAO for user data and performs no other function other than to supply that data to other components within the framework.
In particular, it __does not__ authenticate the user, which is done by the `AuthenticationManager`.
In many cases it makes more sense to <<core-services-authentication-manager,implement `AuthenticationProvider`>> directly if you require a custom authentication process.
In many cases it makes more sense to implement `AuthenticationProvider` directly if you require a custom authentication process.
====
@ -188,7 +188,7 @@ All you need to do is write a filter (or equivalent) that reads the third-party
In this case you also need to think about things which are normally taken care of automatically by the built-in authentication infrastructure.
For example, you might need to pre-emptively create an HTTP session to <<tech-intro-sec-context-persistence,cache the context between requests>>, before you write the response to the client footnote:[It isn't possible to create a session once the response has been committed.].
If you're wondering how the `AuthenticationManager` is implemented in a real world example, we'll look at that in the <<core-services-authentication-manager,core services chapter>>.
If you're wondering how the `AuthenticationManager` is implemented in a real world example, we'll look at that in the <<servlet-authentication-authenticationmanager,`AuthenticationManager`>>.
[[tech-intro-web-authentication]]

View File

@ -5,6 +5,6 @@
The `Authentication` that is returned is then set on the <<servlet-authentication-securitycontextholder>>.
If you are not integrating with <<servlet-filterchainproxy,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, Spring Security provides `ProviderManager` which allows users to provide multiple `AuthenticationProvider` implementations.
While the implementation of `AuthenticationManager` could be anything, the most common implementation is <<servlet-authentication-providermanager,`ProviderManager`>>.
// FIXME: link to ProviderManager
// FIXME: add configuration

View File

@ -12,9 +12,7 @@ include::abstract-authentication-processing-filter.adoc[leveloffset=+1]
include::authentication-manager.adoc[leveloffset=+1]
// authenticationmanager
// providermanager
include::provider-manager.adoc[leveloffset=+1]
// authenticationprovider

View File

@ -0,0 +1,36 @@
[[servlet-authentication-providermanager]]
= ProviderManager
:figures: images/servlet/authentication/architecture
{security-api-url}org/springframework/security/authentication/ProviderManager.html[`ProviderManager`] is the most commonly used implementation of <<servlet-authentication-authenticationmanager,`AuthenticationManager`>>.
`ProviderManager` delegates to a `List` of ``AuthenticationProvider``s.
// FIXME: link to AuthenticationProvider
Each `AuthenticationProvider` has an opportunity to indicate that authentication should be successful, fail, or indicate it cannot make a decision and allow a downstream `AuthenticationProvider` to decide.
If none of the configured ``AuthenticationProvider``s can authenticate, then authentication will fail with a `ProviderNotFoundException` which is a special `AuthenticationException` that indicates the `ProviderManager` was not configured support the type of `Authentication` that was passed into it.
image::{figures}/providermanager.png[]
In practice each `AuthenticationProvider` knows how to perform a specific type of authentication.
For example, one `AuthenticationProvider` might be able to validate a username/password, while another might be able to authenticate a SAML assertion.
This allows each `AuthenticationProvider` to do a very specific type of authentication, while supporting multiple types of authentication and only exposing a single `AuthenticationManager` bean.
`ProviderManager` also allows configuring an optional parent `AuthenticationManager` which is consulted in the event that no `AuthenticationProvider` can perform authentication.
The parent can be any type of `AuthenticationManager`, but it is often an instance of `ProviderManager`.
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 <<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[]
[[servlet-authentication-providermanager-erasing-credentials]]
By default `ProviderManager` will attempt to clear any sensitive credentials information from the `Authentication` object which is returned by a successful authentication request.
This prevents information like passwords being retained longer than necessary in the `HttpSession`.
This may cause issues when you are using a cache of user objects, for example, to improve performance in a stateless application.
If the `Authentication` contains a reference to an object in the cache (such as a `UserDetails` instance) and this has its credentials removed, then it will no longer be possible to authenticate against the cached value.
You need to take this into account if you are using a cache.
An obvious solution is to make a copy of the object first, either in the cache implementation or in the `AuthenticationProvider` which creates the returned `Authentication` object.
Alternatively, you can disable the `eraseCredentialsAfterAuthentication` property on `ProviderManager`.
See the {security-api-url}org/springframework/security/authentication/ProviderManager.html[Javadoc] for more information.

View File

@ -7,16 +7,25 @@ This section discusses:
[[servlet-authentication-architecture]]
*Architecture Components*
This section describes 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 in specific sections.
// FIXME: add for example see form login if you want to see more concrete flows.
* <<servlet-authentication-securitycontextholder>> - The `SecurityContextHolder` is where Spring Security stores the details of who is <<authentication,authenticated>>.
* <<servlet-authentication-securitycontext>> - is obtained from the `SecurityContextHolder` and contains the `Authentication` of the currently authenticated user.
* <<servlet-authentication-authentication>> - Can be the input to `AuthenticationManager` to provide the credentials a user has provided to authenticate or the current user from the `SecurityContext`.
* <<servlet-authentication-granted-authority>> - An authority that is granted to the principal on the `Authentication` (i.e. roles, scopes, etc.)
* <<servlet-authentication-authenticationentrypoint>> - used for requesting credentials from a client (i.e. redirecting to a log in page, sending a `WWW-Authenticate` response, etc.)
* <<servlet-authentication-abstractprocessingfilter>> - a base `Filter` used for authentication
* <<servlet-authentication-abstractprocessingfilter>> - a base `Filter` used for authentication.
This also gives a good idea of the high level flow of authentication and how pieces work together.
* <<servlet-authentication-authenticationmanager>> - the API that defines how Spring Security's Filters perform <<authentication,authentication>>.
* <<servlet-authentication-providermanager>> - the most common implementation of `AuthenticationManager`.
[[servlet-authentication-mechanisms]]
*Authentication Mechanisms*
// FIXME: brief description
* <<servlet-authentication-unpwd>> - how to authenticate with a username/password
// FIXME: Add other mechanisms

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB