Java Spring LDAP#
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import javax.naming.Context;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.core.support.AbstractContextMapper;
import org.springframework.ldap.core.support.DirContextSource;
import org.springframework.ldap.support.LdapUtils;
/**
* This Service does user authentication with LDAP. It uses Spring to do the authentication
*
* A good chunk of the LDAP code is copy-paste from:
* http://static.springsource.organization/spring-ldap/docs/1.3.x/reference/pdf/spring-ldap-reference.pdf
*
*/
public class LDAPService {
private Map<String, String> ldapPropertiesMap=new HashMap<String, String>();
// LDAP Settings
public static final String LDAP_PROVIDER_URL = "ldap.provider.url";
public static final String LDAP_SECURITY_AUTHENTICATION = "ldap.security.authentication";
public static final String LDAP_SECURITY_PRINCIPAL = "ldap.security.principal";
public static final String LDAP_SECURITY_CREDENTIALS = "ldap.security.credentials";
public static final String LDAP_ADMIN_OU = "ldap.admin.ou";
public static final String LDAP_USER_OU = "ldap.user.ou";
public static final String LDAP_USER_FILTER = "ldap.user.filter";
private DirContextSource dirCtxSrc;
private String userAuthority;
private static final String ldapFactory = "com.sun.jndi.ldap.LdapCtxFactory";
private static final String DEFAULT_USER_FILTER = "uid";
public LDAPService() throws Exception {
ldapPropertiesMap.put(LDAP_PROVIDER_URL, "ldap://10.0.1.1:10389/ou=system");
ldapPropertiesMap.put(LDAP_SECURITY_AUTHENTICATION, "simple");
ldapPropertiesMap.put(LDAP_SECURITY_PRINCIPAL, "uid=admin,ou=system");
ldapPropertiesMap.put(LDAP_SECURITY_CREDENTIALS, "secret");
ldapPropertiesMap.put(LDAP_ADMIN_OU, "ou=admins,ou=system");
ldapPropertiesMap.put(LDAP_USER_OU, "ou=users,ou=system");
ldapPropertiesMap.put(LDAP_USER_FILTER, "uid=?");
this.init();
}
private void init() throws Exception {
Hashtable<String, String> env = new Hashtable<String, String>();
env.put(Context.INITIAL_CONTEXT_FACTORY, ldapFactory);
env.put(Context.PROVIDER_URL, ldapPropertiesMap.get(LDAP_PROVIDER_URL));
env.put(Context.SECURITY_AUTHENTICATION,
ldapPropertiesMap.get(LDAP_SECURITY_AUTHENTICATION));
env.put(Context.SECURITY_PRINCIPAL,
ldapPropertiesMap.get(LDAP_SECURITY_PRINCIPAL));
env.put(Context.SECURITY_CREDENTIALS,
ldapPropertiesMap.get(LDAP_SECURITY_CREDENTIALS));
dirCtxSrc = new DirContextSource();
dirCtxSrc.setBaseEnvironmentProperties(env);
dirCtxSrc.setUserDn(ldapPropertiesMap.get(LDAP_SECURITY_PRINCIPAL));
dirCtxSrc.setPassword(ldapPropertiesMap.get(LDAP_SECURITY_CREDENTIALS));
dirCtxSrc.setUrl(ldapPropertiesMap.get(LDAP_PROVIDER_URL));
dirCtxSrc.afterPropertiesSet();
}
/**
* Return user authority after authentication
*
* @return
*/
public String getUserAuthority() {
return userAuthority;
}
public boolean validateLoginCredentials(String username, String password)
throws Exception {
boolean result = false;
try {
String userDn = getDnForUser(username);
result = authenticate(userDn, password);
if (result) {
String adminGroup = ldapPropertiesMap.get(LDAP_ADMIN_OU);
String userGroup = ldapPropertiesMap.get(LDAP_USER_OU);
if (adminGroup != null
&& userDn.toLowerCase().endsWith(
adminGroup.toLowerCase())) {
this.userAuthority = adminGroup;
} else if (userGroup != null
&& userDn.toLowerCase().endsWith(
userGroup.toLowerCase())) {
this.userAuthority = userGroup;
} else {
logger.info(username
+ " is a valid user, but is not in the either the UserOU or AdminOU");
throw new RuntimeException(
"Could not locate Authority for User: '" + username
+ "' in LDAP");
}
}
return result;
} catch (Exception ex) {
logger.error("Exception during ldap authentication for User: '"
+ username + "'", ex);
throw ex;
}
}
/**
* This will find the distinguished name given a uid
*
* @param uid
* @return
*/
protected String getDnForUser(String uid) {
LdapTemplate ldapTemplate = new LdapTemplate(dirCtxSrc);
// Filter
String userFilter = ldapPropertiesMap.get(LDAP_USER_FILTER);
if (userFilter != null && !userFilter.isEmpty()) {
userFilter = userFilter.replaceAll("\?", uid);
} else {
userFilter = "(" + DEFAULT_USER_FILTER + "=" + uid + ")";
}
Logger.debug("LDAP USER Filter:" + userFilter);
// Filter f = new EqualsFilter("uid", uid);
List result = ldapTemplate.search(DistinguishedName.EMPTY_PATH,
userFilter, new AbstractContextMapper() {
protected Object doMapFromContext(DirContextOperations ctx) {
return ctx.getNameInNamespace();
}
});
if (result.size() != 1) {
throw new RuntimeException("User-'" + uid
+ "' not found in LDAP or not unique");
}
return (String) result.get(0);
}
/**
* This try to create a Context using the supplied username and password
*
* @param userDn
* @param password
* @return
*/
protected boolean authenticate(String userDn, String password)
throws Exception {
DirContext ctx = null;
Hashtable<String, String> env = new Hashtable<String, String>();
String providerUrl = (ldapPropertiesMap.get(LDAP_PROVIDER_URL));
String securityAuth = (ldapPropertiesMap
.get(LDAP_SECURITY_AUTHENTICATION));
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, providerUrl);
env.put(Context.SECURITY_AUTHENTICATION, securityAuth);
env.put(Context.SECURITY_PRINCIPAL, userDn);
env.put(Context.SECURITY_CREDENTIALS, password);
try {
ctx = new InitialDirContext(env);
return true;
} catch (Exception e) {
// Context creation failed - authentication did not succeed
logger.error("Login failed for userDn-'" + userDn + "'",
e);
throw e;
} finally {
// It is imperative that the created DirContext instance is always
// closed
LdapUtils.closeContext(ctx);
}
}
public Map<String, String> getLdapPropertiesMap() {
return ldapPropertiesMap;
}
public void setLdapPropertiesMap(Map<String, String> ldapPropertiesMap) {
this.ldapPropertiesMap = ldapPropertiesMap;
}
}