public abstract class AbstractUserDetailsAuthenticationProvider extends java.lang.Object implements AuthenticationProvider, org.springframework.beans.factory.InitializingBean, org.springframework.context.MessageSourceAware
AuthenticationProvider
that allows subclasses to override and work with
UserDetails
objects. The class is
designed to respond to UsernamePasswordAuthenticationToken
authentication
requests.
Upon successful validation, a UsernamePasswordAuthenticationToken
will be
created and returned to the caller. The token will include as its principal either a
String
representation of the username, or the UserDetails
that was
returned from the authentication repository. Using String
is appropriate
if a container adapter is being used, as it expects String
representations
of the username. Using UserDetails
is appropriate if you require access to
additional properties of the authenticated user, such as email addresses,
human-friendly names etc. As container adapters are not recommended to be used, and
UserDetails
implementations provide additional flexibility, by default a
UserDetails
is returned. To override this default, set the
setForcePrincipalAsString(boolean)
to true
.
Caching is handled by storing the UserDetails
object being placed in the
UserCache
. This ensures that subsequent requests with the same username can be
validated without needing to query the UserDetailsService
. It should be noted
that if a user appears to present an incorrect password, the UserDetailsService
will be queried to confirm the most up-to-date password was used for comparison.
Caching is only likely to be required for stateless applications. In a normal web
application, for example, the SecurityContext is stored in the user's session
and the user isn't reauthenticated on each request. The default cache implementation is
therefore NullUserCache
.
Modifier and Type | Field and Description |
---|---|
protected boolean |
hideUserNotFoundExceptions |
protected org.apache.commons.logging.Log |
logger |
protected org.springframework.context.support.MessageSourceAccessor |
messages |
Constructor and Description |
---|
AbstractUserDetailsAuthenticationProvider() |
Modifier and Type | Method and Description |
---|---|
protected abstract void |
additionalAuthenticationChecks(UserDetails userDetails,
UsernamePasswordAuthenticationToken authentication)
Allows subclasses to perform any additional checks of a returned (or cached)
UserDetails for a given authentication request. |
void |
afterPropertiesSet() |
Authentication |
authenticate(Authentication authentication)
Performs authentication with the same contract as
AuthenticationManager.authenticate(Authentication)
. |
protected Authentication |
createSuccessAuthentication(java.lang.Object principal,
Authentication authentication,
UserDetails user)
Creates a successful
Authentication object. |
protected void |
doAfterPropertiesSet() |
protected UserDetailsChecker |
getPostAuthenticationChecks() |
protected UserDetailsChecker |
getPreAuthenticationChecks() |
UserCache |
getUserCache() |
boolean |
isForcePrincipalAsString() |
boolean |
isHideUserNotFoundExceptions() |
protected abstract UserDetails |
retrieveUser(java.lang.String username,
UsernamePasswordAuthenticationToken authentication)
Allows subclasses to actually retrieve the
UserDetails from an
implementation-specific location, with the option of throwing an
AuthenticationException immediately if the presented credentials are
incorrect (this is especially useful if it is necessary to bind to a resource as
the user in order to obtain or generate a UserDetails ). |
void |
setAuthoritiesMapper(GrantedAuthoritiesMapper authoritiesMapper) |
void |
setForcePrincipalAsString(boolean forcePrincipalAsString) |
void |
setHideUserNotFoundExceptions(boolean hideUserNotFoundExceptions)
By default the
AbstractUserDetailsAuthenticationProvider throws a
BadCredentialsException if a username is not found or the password is
incorrect. |
void |
setMessageSource(org.springframework.context.MessageSource messageSource) |
void |
setPostAuthenticationChecks(UserDetailsChecker postAuthenticationChecks) |
void |
setPreAuthenticationChecks(UserDetailsChecker preAuthenticationChecks)
Sets the policy will be used to verify the status of the loaded
UserDetails before validation of the credentials takes place.
|
void |
setUserCache(UserCache userCache) |
boolean |
supports(java.lang.Class<?> authentication)
Returns
true if this AuthenticationProvider supports the
indicated Authentication object. |
protected final org.apache.commons.logging.Log logger
protected org.springframework.context.support.MessageSourceAccessor messages
protected boolean hideUserNotFoundExceptions
public AbstractUserDetailsAuthenticationProvider()
protected abstract void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException
UserDetails
for a given authentication request. Generally a subclass
will at least compare the Authentication.getCredentials()
with a
UserDetails.getPassword()
. If custom logic is needed to compare additional
properties of UserDetails
and/or
UsernamePasswordAuthenticationToken
, these should also appear in this
method.userDetails
- as retrieved from the
retrieveUser(String, UsernamePasswordAuthenticationToken)
or
UserCache
authentication
- the current request that needs to be authenticatedAuthenticationException
- AuthenticationException if the credentials could
not be validated (generally a BadCredentialsException
, an
AuthenticationServiceException
)public final void afterPropertiesSet() throws java.lang.Exception
afterPropertiesSet
in interface org.springframework.beans.factory.InitializingBean
java.lang.Exception
public Authentication authenticate(Authentication authentication) throws AuthenticationException
AuthenticationProvider
AuthenticationManager.authenticate(Authentication)
.authenticate
in interface AuthenticationProvider
authentication
- the authentication request object.null
if the AuthenticationProvider
is unable to support
authentication of the passed Authentication
object. In such a case,
the next AuthenticationProvider
that supports the presented
Authentication
class will be tried.AuthenticationException
- if authentication fails.protected Authentication createSuccessAuthentication(java.lang.Object principal, Authentication authentication, UserDetails user)
Authentication
object.
Protected so subclasses can override.
Subclasses will usually store the original credentials the user supplied (not
salted or encoded passwords) in the returned Authentication
object.
principal
- that should be the principal in the returned object (defined by
the isForcePrincipalAsString()
method)authentication
- that was presented to the provider for validationuser
- that was loaded by the implementationprotected void doAfterPropertiesSet() throws java.lang.Exception
java.lang.Exception
public UserCache getUserCache()
public boolean isForcePrincipalAsString()
public boolean isHideUserNotFoundExceptions()
protected abstract UserDetails retrieveUser(java.lang.String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException
UserDetails
from an
implementation-specific location, with the option of throwing an
AuthenticationException
immediately if the presented credentials are
incorrect (this is especially useful if it is necessary to bind to a resource as
the user in order to obtain or generate a UserDetails
).
Subclasses are not required to perform any caching, as the
AbstractUserDetailsAuthenticationProvider
will by default cache the
UserDetails
. The caching of UserDetails
does present
additional complexity as this means subsequent requests that rely on the cache will
need to still have their credentials validated, even if the correctness of
credentials was assured by subclasses adopting a binding-based strategy in this
method. Accordingly it is important that subclasses either disable caching (if they
want to ensure that this method is the only method that is capable of
authenticating a request, as no UserDetails
will ever be cached) or
ensure subclasses implement
additionalAuthenticationChecks(UserDetails, UsernamePasswordAuthenticationToken)
to compare the credentials of a cached UserDetails
with subsequent
authentication requests.
Most of the time subclasses will not perform credentials inspection in this method,
instead performing it in
additionalAuthenticationChecks(UserDetails, UsernamePasswordAuthenticationToken)
so that code related to credentials validation need not be duplicated across two
methods.
username
- The username to retrieveauthentication
- The authentication request, which subclasses may
need to perform a binding-based retrieval of the UserDetails
null
- instead an exception should
the thrown)AuthenticationException
- if the credentials could not be validated
(generally a BadCredentialsException
, an
AuthenticationServiceException
or
UsernameNotFoundException
)public void setForcePrincipalAsString(boolean forcePrincipalAsString)
public void setHideUserNotFoundExceptions(boolean hideUserNotFoundExceptions)
AbstractUserDetailsAuthenticationProvider
throws a
BadCredentialsException
if a username is not found or the password is
incorrect. Setting this property to false
will cause
UsernameNotFoundException
s to be thrown instead for the former. Note
this is considered less secure than throwing BadCredentialsException
for both exceptions.hideUserNotFoundExceptions
- set to false
if you wish
UsernameNotFoundException
s to be thrown instead of the non-specific
BadCredentialsException
(defaults to true
)public void setMessageSource(org.springframework.context.MessageSource messageSource)
setMessageSource
in interface org.springframework.context.MessageSourceAware
public void setUserCache(UserCache userCache)
public boolean supports(java.lang.Class<?> authentication)
AuthenticationProvider
true
if this AuthenticationProvider
supports the
indicated Authentication
object.
Returning true
does not guarantee an
AuthenticationProvider
will be able to authenticate the presented
instance of the Authentication
class. It simply indicates it can
support closer evaluation of it. An AuthenticationProvider
can still
return null
from the AuthenticationProvider.authenticate(Authentication)
method to
indicate another AuthenticationProvider
should be tried.
Selection of an AuthenticationProvider
capable of performing
authentication is conducted at runtime the ProviderManager
.
supports
in interface AuthenticationProvider
true
if the implementation can more closely evaluate the
Authentication
class presentedprotected UserDetailsChecker getPreAuthenticationChecks()
public void setPreAuthenticationChecks(UserDetailsChecker preAuthenticationChecks)
preAuthenticationChecks
- strategy to be invoked prior to authentication.protected UserDetailsChecker getPostAuthenticationChecks()
public void setPostAuthenticationChecks(UserDetailsChecker postAuthenticationChecks)
public void setAuthoritiesMapper(GrantedAuthoritiesMapper authoritiesMapper)