public class LdapAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider
AuthenticationProvider
implementation that provides integration with an
LDAP server.
There are many ways in which an LDAP directory can be configured so this class delegates most of
its responsibilites to two separate strategy interfaces, LdapAuthenticator
and LdapAuthoritiesPopulator
.
BindAuthenticator
which authenticates the user by
"binding" as that user, and PasswordComparisonAuthenticator
which performs a comparison of the supplied password with the value stored in the
directory, either by retrieving the password or performing an LDAP "compare" operation.
The task of retrieving the user attributes is delegated to the authenticator because the permissions on the attributes may depend on the type of authentication being used; for example, if binding as the user, it may be necessary to read them with the user's own permissions (using the same context used for the bind operation).
DefaultLdapAuthoritiesPopulator
can be configured to obtain user role information from the user's attributes and/or to perform a search for
"groups" that the user is a member of and map these to roles.
A custom implementation could obtain the roles from a completely different source, for example from a database.
<bean id="initialDirContextFactory" class="org.acegisecurity.providers.ldap.DefaultInitialDirContextFactory"> <constructor-arg value="ldap://monkeymachine:389/dc=acegisecurity,dc=org"/> <property name="managerDn"><value>cn=manager,dc=acegisecurity,dc=org</value></property> <property name="managerPassword"><value>password</value></property> </bean> <bean id="ldapAuthProvider" class="org.acegisecurity.providers.ldap.LdapAuthenticationProvider"> <constructor-arg> <bean class="org.acegisecurity.providers.ldap.authenticator.BindAuthenticator"> <constructor-arg><ref local="initialDirContextFactory"/></constructor-arg> <property name="userDnPatterns"><list><value>uid={0},ou=people</value></list></property> </bean> </constructor-arg> <constructor-arg> <bean class="org.acegisecurity.providers.ldap.populator.DefaultLdapAuthoritiesPopulator"> <constructor-arg><ref local="initialDirContextFactory"/></constructor-arg> <constructor-arg><value>ou=groups</value></constructor-arg> <property name="groupRoleAttribute"><value>ou</value></property> </bean> </constructor-arg> </bean>
This would set up the provider to access an LDAP server with URL ldap://monkeymachine:389/dc=acegisecurity,dc=org. Authentication will be performed by attempting to bind with the DN uid=<user-login-name>,ou=people,dc=acegisecurity,dc=org. After successful authentication, roles will be assigned to the user by searching under the DN ou=groups,dc=acegisecurity,dc=org with the default filter (member=<user's-DN>). The role name will be taken from the "ou" attribute of each match.
The authenticate method will reject empty passwords outright. LDAP servers may allow an anonymous bind operation with an empty password, even if a DN is supplied. In practice this means that if the LDAP directory is configured to allow unauthenitcated access, it might be possible to authenticate as any user just by supplying an empty password. More information on the misuse of unauthenticated access can be found in draft-ietf-ldapbis-authmeth-19.txt.
BindAuthenticator
,
DefaultLdapAuthoritiesPopulator
hideUserNotFoundExceptions, messages
Constructor and Description |
---|
LdapAuthenticationProvider(LdapAuthenticator authenticator)
Creates an instance with the supplied authenticator and a null authorities populator.
|
LdapAuthenticationProvider(LdapAuthenticator authenticator,
LdapAuthoritiesPopulator authoritiesPopulator)
Create an instance with the supplied authenticator and authorities populator implementations.
|
Modifier and Type | Method and Description |
---|---|
protected void |
additionalAuthenticationChecks(UserDetails userDetails,
UsernamePasswordAuthenticationToken authentication)
Allows subclasses to perform any additional checks of a returned (or cached)
UserDetails
for a given authentication request. |
protected UserDetails |
createUserDetails(LdapUserDetails ldapUser,
String username,
String password)
Creates the final UserDetails object that will be returned by the provider once the user has
been authenticated.
|
protected LdapAuthoritiesPopulator |
getAuthoritiesPopulator() |
boolean |
isIncludeDetailsObject() |
protected UserDetails |
retrieveUser(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 |
setIncludeDetailsObject(boolean includeDetailsObject) |
afterPropertiesSet, authenticate, createSuccessAuthentication, doAfterPropertiesSet, getPostAuthenticationChecks, getPreAuthenticationChecks, getUserCache, isForcePrincipalAsString, isHideUserNotFoundExceptions, setForcePrincipalAsString, setHideUserNotFoundExceptions, setMessageSource, setPostAuthenticationChecks, setPreAuthenticationChecks, setUserCache, supports
public LdapAuthenticationProvider(LdapAuthenticator authenticator, LdapAuthoritiesPopulator authoritiesPopulator)
authenticator
- the authentication strategy (bind, password comparison, etc)
to be used by this provider for authenticating users.authoritiesPopulator
- the strategy for obtaining the authorities for a given user after they've been
authenticated.public LdapAuthenticationProvider(LdapAuthenticator authenticator)
authenticator
- the authenticator strategy.protected LdapAuthoritiesPopulator getAuthoritiesPopulator()
protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException
AbstractUserDetailsAuthenticationProvider
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.additionalAuthenticationChecks
in class AbstractUserDetailsAuthenticationProvider
userDetails
- as retrieved from the AbstractUserDetailsAuthenticationProvider.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
)protected UserDetails createUserDetails(LdapUserDetails ldapUser, String username, String password)
The LdapAuthoritiesPopulator will be used to create the granted authorites for the user.
Can be overridden to customize the creation of the final UserDetails instance. The default will merge any additional authorities retrieved from the populator with the propertis of original ldapUser object and set the values of the username and password.
ldapUser
- The intermediate LdapUserDetails instance returned by the authenticator.username
- the username submitted to the providerpassword
- the password submitted to the providerprotected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException
AbstractUserDetailsAuthenticationProvider
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 AbstractUserDetailsAuthenticationProvider.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 AbstractUserDetailsAuthenticationProvider.additionalAuthenticationChecks(UserDetails, UsernamePasswordAuthenticationToken)
so
that code related to credentials validation need not be duplicated across two methods.
retrieveUser
in class AbstractUserDetailsAuthenticationProvider
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 boolean isIncludeDetailsObject()
public void setIncludeDetailsObject(boolean includeDetailsObject)
Copyright © 2014. All rights reserved.