While the core functionality of the ContextSource
is to provide
DirContext
instances for use by LdapTemplate
,
it may also be used for authenticating users against an LDAP server. The
getContext(principal, credentials)
method of ContextSource
will do exactly that; construct a DirContext
instance according to the
ContextSource
configuration, authenticating the context using the
supplied principal and credentials.
Example 10.1. Using ContextSource
for user authentication
public boolean authenticate(String userDn, String credentials) { DirContext ctx = null; try { ctx = contextSource.getContext(userDn, credentials); return true; } catch (Exception e) { // Context creation failed - authentication did not succeed logger.error("Login failed", e); return false; } finally { // It is imperative that the created DirContext instance is always closed LdapUtils.closeContext(ctx); } }
The userDn supplied to the authenticate
method needs to be the full
DN of the user to authenticate (regardless of the base
setting on the
ContextSource
). You will typically need to perform an LDAP search
based on e.g. the user name to get this DN:
Example 10.2. Finding a user based on uid attribute.
private String getDnForUser(String uid) { Filter f = new EqualsFilter("uid", uid); List result = ldapTemplate.search(DistinguishedName.EMPTY_PATH, f.toString(), new AbstractContextMapper() { protected Object doMapFromContext(DirContextOperations ctx) { return ctx.getNameInNamespace(); } }); if(result.size() != 1) { throw new RuntimeException("User not found or not unique"); } return (String)result.get(0); }
Some authentication schemes and LDAP servers require some operation to be
performed on the created DirContext
instance for the actual
authentication to occur. You should test and make sure how your server setup and
authentication schemes behave; failure to do so might result in that users
will be admitted into your system regardless of the DN/credentials supplied.
Example 10.3. Performing LDAP operation on returned DirContext
objects.
public boolean authenticate(String userDn, String credentials) { DirContext ctx = null; try { ctx = contextSource.getContext(userDn, credentials); // Take care here - if a base was specified on the ContextSource // that needs to be removed from the user DN for the lookup to succeed. ctx.lookup(userDn); return true; } catch (Exception e) { // Context creation failed - authentication did not succeed logger.error("Login failed", e); return false; } finally { // It is imperative that the created DirContext instance is always closed LdapUtils.closeContext(ctx); } }
While the approach above may be sufficient for very simple authentication scenarios, requirements in this area commonly expand rapidly. There is a multitude of aspects that apply to this area, including authentication, authorization, web integration, user context management, etc. If you suspect that the requirements might expand you should definitely consider using Spring Security for your security purposes instead. It is a full-blown, mature security framework addressing the above aspects as well as several others.