package com.xxxpiao.common.utils; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Hashtable; import javax.naming.Context; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.naming.directory.Attribute; 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 org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.sun.org.apache.xerces.internal.impl.dv.util.Base64; @SuppressWarnings("restriction") public class LdapHelper { private static DirContext dirContext; public static Logger logger = LoggerFactory.getLogger(LdapHelper.class); /** * 默认账号连接LDAP服务器 * @return */ @SuppressWarnings(value = "unchecked") public static DirContext getDirContext() { String account = "cn=xxxadmin,ou=authusers,dc=2caipiao,dc=com"; //binddn String password = "Yae0zohV2mieJooCho"; //bindpwd String root = "dc=2caipiao,dc=com"; // root Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.PROVIDER_URL, "ldap://192.168.90.144:389/" + root); env.put(Context.SECURITY_AUTHENTICATION, "simple"); env.put(Context.SECURITY_PRINCIPAL, account); env.put(Context.SECURITY_CREDENTIALS, password); try { // 链接ldap dirContext = new InitialDirContext(env); logger.info("认证成功!"); } catch (javax.naming.AuthenticationException e) { logger.error("认证失败:"+e.toString()); } catch (Exception e) { logger.error("认证失败:"+e.toString()); } return dirContext; } /** * * @param ldapAccount 连接LDAP服务器账号 * @param ldapPassword 连接LDAP服务器密码 * @param ldapRoot LDAP服务器根目录 * @param ldapServerIP LDAP服务器IP * @return */ @SuppressWarnings(value = "unchecked") public static DirContext getDirContext(String ldapAccount,String ldapPassword,String ldapRoot,String ldapServerIP) { Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.PROVIDER_URL, "ldap://"+ldapServerIP+":389/" + ldapRoot); env.put(Context.SECURITY_AUTHENTICATION, "simple"); env.put(Context.SECURITY_PRINCIPAL, ldapAccount); env.put(Context.SECURITY_CREDENTIALS, ldapPassword); try { // 链接ldap dirContext = new InitialDirContext(env); logger.info("认证成功!"); } catch (javax.naming.AuthenticationException e) { logger.error("认证失败:"+e.toString()); } catch (Exception e) { logger.error("认证失败:"+e.toString()); } return dirContext; } /** * 关闭LDAP连接 */ public static void closeDirCountext(){ try { if(dirContext!=null){ dirContext.close(); } } catch (NamingException ex) { logger.error(ex.toString()); } } /** * 验证密码的是否一致 * @param ldapPassword 从LDAP服务器获取的密码 * @param inputPassword 用户输入的密码 * @return * @throws NoSuchAlgorithmException */ @SuppressWarnings(value = "unchecked") public static boolean verifySHA(String ldapPassword, String inputPassword) throws NoSuchAlgorithmException { // MessageDigest 提供了消息摘要算法,如 MD5 或 SHA,的功能,这里LDAP使用的是SHA-1 MessageDigest md = MessageDigest.getInstance("SHA-1"); // 取出加密字符 if (ldapPassword.startsWith("{SSHA}")) { ldapPassword = ldapPassword.substring(6); } else if (ldapPassword.startsWith("{SHA}")) { ldapPassword = ldapPassword.substring(5); } // 解码BASE64 byte[] ldappwbyte = Base64.decode(ldapPassword); byte[] shacode; byte[] salt; // 前20位是SHA-1加密段,20位后是最初加密时的随机明文 if (ldappwbyte.length <= 20) { shacode = ldappwbyte; salt = new byte[0]; } else { shacode = new byte[20]; salt = new byte[ldappwbyte.length - 20]; System.arraycopy(ldappwbyte, 0, shacode, 0, 20); System.arraycopy(ldappwbyte, 20, salt, 0, salt.length); } // 把用户输入的密码添加到摘要计算信息 md.update(inputPassword.getBytes()); // 把随机明文添加到摘要计算信息 md.update(salt); // 按SSHA把当前用户密码进行计算 byte[] inputpwbyte = md.digest(); // 返回校验结果 return MessageDigest.isEqual(shacode, inputpwbyte); } /** * 验证用户名密码 * @param ldapAccount 连接LDAP服务器账号 * @param ldapPassword 连接LDAP服务器密码 * @param ldapRoot LDAP服务器根目录 * @param ldapServerIP LDAP服务器IP * @param account 用户账号 * @param password 用户密码 * @return */ public static boolean authenticate(String ldapAccount,String ldapPassword,String ldapRoot,String ldapServerIP,String account, String password) { boolean success = false; DirContext dirContext = null; try { dirContext = LdapHelper.getDirContext(ldapAccount, ldapPassword, ldapRoot, ldapServerIP); SearchControls constraints = new SearchControls(); constraints.setSearchScope(SearchControls.SUBTREE_SCOPE); NamingEnumeration en = dirContext.search("", "cn=" + account, constraints); // 查询所有用户 while (en != null && en.hasMoreElements()) { Object obj = en.nextElement(); if (obj instanceof SearchResult) { SearchResult si = (SearchResult) obj; logger.info("name:"+si.getName()); Attributes attrs = si.getAttributes(); if (attrs == null) { System.out.println("No attributes"); } else { Attribute attr = attrs.get("userPassword"); Object o = attr.get(); byte[] s = (byte[]) o; String passwordFromLdap = new String(s); success = LdapHelper.verifySHA(passwordFromLdap, password); return success; } } else { logger.info(obj.toString()); } } dirContext.close(); } catch (NoSuchAlgorithmException ex) { try { if (dirContext != null) { dirContext.close(); } } catch (NamingException namingException) { logger.error(namingException.toString()); } logger.error(ex.toString()); } catch (NamingException ex) { try { if (dirContext != null) { dirContext.close(); } } catch (NamingException namingException) { logger.error(namingException.toString()); } logger.error(ex.toString()); } return false; } /** * 验证用户名密码(走默认的LDAP账号) * @param account 用户名 * @param password 用户密码 * @return */ public static boolean authenticate(String account, String password) { boolean success = false; DirContext dirContext = null; try { dirContext = LdapHelper.getDirContext(); SearchControls constraints = new SearchControls(); constraints.setSearchScope(SearchControls.SUBTREE_SCOPE); NamingEnumeration en = dirContext.search("", "cn=" + account, constraints); // 查询所有用户 while (en != null && en.hasMoreElements()) { Object obj = en.nextElement(); if (obj instanceof SearchResult) { SearchResult si = (SearchResult) obj; logger.info("name:"+si.getName()); Attributes attrs = si.getAttributes(); if (attrs == null) { System.out.println("No attributes"); } else { Attribute attr = attrs.get("userPassword"); Object o = attr.get(); byte[] s = (byte[]) o; String ldapPassword = new String(s); success = LdapHelper.verifySHA(ldapPassword, password); return success; } } else { logger.info(obj.toString()); } } dirContext.close(); } catch (NoSuchAlgorithmException ex) { try { if (dirContext != null) { dirContext.close(); } } catch (NamingException namingException) { logger.error(namingException.toString()); } logger.error(ex.toString()); } catch (NamingException ex) { try { if (dirContext != null) { dirContext.close(); } } catch (NamingException namingException) { logger.error(namingException.toString()); } logger.error(ex.toString()); } return false; } public static void main(String[] args) { System.out.println(authenticate("congmin.jin", "00")); System.out.println(authenticate("cn=xxxadmin,ou=authusers,dc=2caipiao,dc=com", "Yae0zohV2mieJooCho", "dc=2caipiao,dc=com", "192.168.90.144", "congmin.jin", "11")); } }