All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hfg.ldap.LDAPClient Maven / Gradle / Ivy

There is a newer version: 20240423
Show newest version
package com.hfg.ldap;


import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.naming.AuthenticationException;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;

import com.hfg.security.LoginCredentials;
import com.hfg.util.StringUtil;
import com.hfg.util.collection.CollectionUtil;

//------------------------------------------------------------------------------
/**
 Simple LDAP Client.
 
@author J. Alex Taylor, hairyfatguy.com
*/ //------------------------------------------------------------------------------ // com.hfg XML/HTML Coding Library // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com // [email protected] //------------------------------------------------------------------------------ public class LDAPClient { private String mLDAP_ServerURL; private String mLDAP_UserContext; private String mLDAP_PrincipalFieldName = "uid"; private String mLDAP_PrincipalContext; private String mLDAP_PrincipalSuffix; private LoginCredentials mLDAP_PrincipalCredentials; private static final Logger LOGGER = Logger.getLogger(LDAPClient.class.getName()); private static final Pattern sADAuthenticationExceptionPattern = Pattern.compile("AcceptSecurityContext error, data (\\S+?), "); //--------------------------------------------------------------------------- public LDAPClient setServerURL(String inValue) { mLDAP_ServerURL = inValue; return this; } //--------------------------------------------------------------------------- public LDAPClient setUserContext(String inValue) { mLDAP_UserContext = inValue; return this; } //--------------------------------------------------------------------------- public LDAPClient setPrincipalContext(String inValue) { mLDAP_PrincipalContext = inValue; return this; } //--------------------------------------------------------------------------- public LDAPClient setPrincipalSuffix(String inValue) { mLDAP_PrincipalSuffix = inValue; return this; } //--------------------------------------------------------------------------- /** Specifies the credentials to be used to access the LDAP server. * @param inValue the security principal credentials * @return this LDAPClient object to facilitate method chaining */ public LDAPClient setPrincipalCredentials(LoginCredentials inValue) { mLDAP_PrincipalCredentials = inValue; return this; } //--------------------------------------------------------------------------- public LDAPClient setPrincipalFieldName(String inValue) { mLDAP_PrincipalFieldName = inValue; return this; } //--------------------------------------------------------------------------- // TODO: Should this method return a more complex result that could contain more info about failures? public boolean authenticate(LoginCredentials inCredentials) { crosscheck(); boolean authenticated = false; DirContext ctx = null; try { // Create the initial context ctx = getInitialDirContext(inCredentials); if (ctx != null) { authenticated = true; } /* // get more attributes about this user SearchControls scs = new SearchControls(); scs.setSearchScope(SearchControls.SUBTREE_SCOPE); String[] attrNames = { "mail", "cn" }; scs.setReturningAttributes(attrNames); NamingEnumeration nes = ctx.search(mLDAP_UserContext, "uid=" + userName, scs); if(nes.hasMore()) { Attributes attrs = ((SearchResult) nes.next()).getAttributes(); System.out.println("mail: " + attrs.get("mail").get()); System.out.println("cn: " + attrs.get("cn").get()); } */ } catch (AuthenticationException e) { // If it looks like an Active Directory exception, try to decode it... String msg = decodeActiveDirectoryAuthenticationException(e); if (StringUtil.isSet(msg)) { new LDAP_Exception(msg, e).printStackTrace(); } else { e.printStackTrace(); } } catch (NamingException e) { e.printStackTrace(); } finally { if (ctx != null) { try { ctx.close(); } catch (NamingException e) { // Ignore } } } return authenticated; } //--------------------------------------------------------------------------- public LDAP_User getInfoForUser(String inQuery) { return getInfoForUser(inQuery, null); } //--------------------------------------------------------------------------- public LDAP_User getInfoForUser(String inQuery, List inFields) { List users = getInfoForUsers(inQuery, inFields); return (CollectionUtil.hasValues(users) ? users.get(0) : null); } //--------------------------------------------------------------------------- public List getInfoForUsers(String inQuery) { return getInfoForUsers(inQuery, null); } //--------------------------------------------------------------------------- public List getInfoForUsers(String inFilter, List inFields) { List users = null; DirContext ctx = null; try { // Create the initial context ctx = getInitialDirContext(mLDAP_PrincipalCredentials); // get more attributes about this user SearchControls searchControls = new SearchControls(); searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); Map fieldMap = null; String[] attributesToRetrieve = new String[] {"*"}; // Default to all attributes if (CollectionUtil.hasValues(inFields)) { fieldMap = new HashMap<>(inFields.size()); List attrNames = new ArrayList<>(inFields.size()); for (LDAP_UserField field : inFields) { attrNames.add(field.name()); fieldMap.put(field.name(), field); } attributesToRetrieve = attrNames.toArray(new String[] {}); } searchControls.setReturningAttributes(attributesToRetrieve); LOGGER.info("LDAP Query " + StringUtil.singleQuote(inFilter) + " in context " + mLDAP_UserContext); NamingEnumeration enumeration = ctx.search(mLDAP_UserContext, inFilter, searchControls); while (enumeration.hasMore()) { if (null == users) { users = new ArrayList<>(); } LDAP_User user = new LDAP_User(); users.add(user); Attributes attrs = ((SearchResult) enumeration.next()).getAttributes(); NamingEnumeration attrEnum = attrs.getIDs(); while (attrEnum.hasMoreElements()) { String attrID = attrEnum.nextElement(); if (fieldMap != null) { LDAP_UserField field = fieldMap.get(attrID); if (field != null) { Method setter = field.getUserObjectSetter(); if (setter != null) { try { setter.invoke(user, attrs.get(attrID).get().toString()); } catch (Exception e) { } } } } user.setField(attrID, attrs.get(attrID).get().toString()); } } } catch (NamingException e) { throw new LDAP_Exception(e); } finally { if (ctx != null) { try { ctx.close(); } catch (NamingException e) { } } } return users; } //########################################################################### // PRIVATE METHODS //########################################################################### //--------------------------------------------------------------------------- /** Checks to run before an operation. */ private void crosscheck() { if (null == mLDAP_ServerURL) { throw new LDAP_Exception("No LDAP server has been specified!"); } } //--------------------------------------------------------------------------- private InitialDirContext getInitialDirContext(LoginCredentials inCredentials) throws NamingException { crosscheck(); // creating environment for initial context Hashtable env = new Hashtable<>(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); LOGGER.info("Setting provider URL to " + StringUtil.singleQuote(mLDAP_ServerURL)); env.put(Context.PROVIDER_URL, mLDAP_ServerURL); // env.put(Context.SECURITY_AUTHENTICATION, "simple"); String securityPrincipal = inCredentials.getUser(); // Active Directory may not want more than this if (mLDAP_PrincipalContext != null) { securityPrincipal = mLDAP_PrincipalFieldName + "=" + inCredentials.getUser() + (StringUtil.isSet(mLDAP_PrincipalContext) ? "," + mLDAP_PrincipalContext : ""); } else if (StringUtil.isSet(mLDAP_PrincipalSuffix)) { securityPrincipal += mLDAP_PrincipalSuffix; } LOGGER.info("Setting security principal to " + StringUtil.singleQuote(securityPrincipal)); env.put(Context.SECURITY_PRINCIPAL, securityPrincipal); env.put(Context.SECURITY_CREDENTIALS, inCredentials.getPasswordString()); LOGGER.info("Establishing LDAP connection..."); // Create the initial context return new InitialDirContext(env); } //--------------------------------------------------------------------------- private String decodeActiveDirectoryAuthenticationException(AuthenticationException inException) { // javax.naming.AuthenticationException: [LDAP: error code 49 - 80090308: LdapErr: DSID-0C0903D9, comment: AcceptSecurityContext error, data 52e, v2580 ] String msg = null; if (inException != null && inException.getMessage() != null) { Matcher m = sADAuthenticationExceptionPattern.matcher(inException.getMessage()); if (m.find()) { /* 525 user not found 52e invalid credentials 530 not permitted to logon at this time 531 not permitted to logon at this workstation 532 password expired 533 account disabled 534 The user has not been granted the requested logon type at this machine 701 account expired 773 user must reset password 775 user account locked */ if (m.group(1).equals("525")) { msg = "User not found"; } else if (m.group(1).equals("52e")) { msg = "Invalid credentials"; } else if (m.group(1).equals("530")) { msg = "Not permitted to logon at this time"; } else if (m.group(1).equals("531")) { msg = "Not permitted to logon at this workstation"; } else if (m.group(1).equals("532")) { msg = "Password expired"; } else if (m.group(1).equals("533")) { msg = "Account disabled"; } else if (m.group(1).equals("534")) { msg = "The user has not been granted the requested logon type at this machine"; } else if (m.group(1).equals("701")) { msg = "Account expired"; } else if (m.group(1).equals("773")) { msg = "User must reset password"; } else if (m.group(1).equals("773")) { msg = "User account locked"; } } } return msg; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy