|
@@ -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`.
|