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; } }