在去年南京项目中,客户方要求用户登陆需要在其他平台下进行认证,当时客户用的LDAP“数据库”管理方式,后来查阅Java已经对LDAP进行了封装,不需要下载其他jar包就可以实现。
补脑:【LDAP】是"Lightweight Directory Access Protocol"的缩写,中文翻译过来就叫“轻量目录访问协议”,看字面大概能猜出应该是以树状形存储数据的数据库,后来翻阅资料确实如此。其中包含几个重要的参数:CN,DN,DC,OU。至于这个缩写单词的含义,有兴趣可以去百科或者官网脑补一下,下面程序中将会引用这几个才参数,也会进行简单的描述。
package com.angma.mes.zbe.moudle.service.util; import com.angma.mes.jagybarcode.manager.controller.plan.machine.MachineShopTaskCreateController; import com.sun.org.apache.xerces.internal.impl.dv.util.Base64; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Hashtable; import java.util.logging.Level; import java.util.logging.Logger; import javax.naming.Context; import javax.naming.NamingException; import javax.naming.directory.DirContext; import javax.naming.directory.InitialDirContext; /** * 用户登陆认证,LDAP跨域认证,通过LDAP对用户进行更新 * * @author xlj * @date 2015.07.10 */ public class LdapUtil { private static DirContext ctx; // LDAP服务器端口默认为389 private static final String LDAP_URL = "ldap://127.0.0.1:389"; // ROOT根据此参数确认用户组织所在位置 private static final String LDAP_PRINCIPAL = "OU=CMA Users,DC=changan-mazda,DC=com,DC=cn"; // LDAP驱动 private static final String LDAP_FACTORY = "com.sun.jndi.ldap.LdapCtxFactory"; private static Logger logger = Logger.getLogger(LdapUtil.class); /**** 测试 ****/ public static void main(String[] args) { LdapUtil.getLoginContext(); LdapUtil.addUserLdap("10000", "123456"); LdapUtil.updatePasswordLdap("10000", "1234567"); LdapUtil.deleteUserLdap("10000"); } // 通过连接LDAP服务器对用户进行认证,返回LDAP对象 public static DirContext getLoginContext() { String account = "zhangsan"; // 模拟用户名 String password = "123456"; // 模拟密码 for (int i = 0; i < 5; i++) { // 验证次数 Hashtable env = new Hashtable(); env.put(Context.SECURITY_AUTHENTICATION, "simple"); env.put(Context.SECURITY_CREDENTIALS, password); // cn=属于哪个组织结构名称,ou=某个组织结构名称下等级位置编号 env.put(Context.SECURITY_PRINCIPAL, "cn=" + account + ", ou=Level0" + i + "00," + LDAP_URL); env.put(Context.INITIAL_CONTEXT_FACTORY, LDAP_PRINCIPAL); env.put(Context.PROVIDER_URL, LDAP_FACTORY); try { // 连接LDAP进行认证 ctx = new InitialDirContext(env); System.out.println("认证成功"); logger.info("【" + account + "】用户于【" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "】登陆系统成功"); } catch (javax.naming.AuthenticationException e) { System.out.println("认证失败"); } catch (NamingException err) { logger.info("--------->>【" + account + "】用户验证失败【" + i + "】次"); } catch (Exception e) { System.out.println("认证出错:"); e.printStackTrace(); } } return ctx; } // 将输入用户和密码进行加密算法后验证 public static boolean verifySHA(String ldappw, String inputpw) { // MessageDigest 提供了消息摘要算法,如 MD5 或 SHA,的功能,这里LDAP使用的是SHA-1 MessageDigest md = MessageDigest.getInstance("SHA-1"); // 取出加密字符 if (ldappw.startsWith("{SSHA}")) { ldappw = ldappw.substring(6); } else if (ldappw.startsWith("{SHA}")) { ldappw = ldappw.substring(5); } // 解码BASE64 byte[] ldappwbyte = Base64.decode(ldappw); 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(inputpw.getBytes()); // 把随机明文添加到摘要计算信息 md.update(salt); // 按SSHA把当前用户密码进行计算 byte[] inputpwbyte = md.digest(); // 返回校验结果 return MessageDigest.isEqual(shacode, inputpwbyte); } // 添加用户 public static boolean addUserLdap(String account, String password) { boolean success = false; try { ctx = LdapUtil.getLoginContext(); BasicAttributes attrsbu = new BasicAttributes(); BasicAttribute objclassSet = new BasicAttribute("objectclass"); objclassSet.add("person"); objclassSet.add("top"); objclassSet.add("organizationalPerson"); objclassSet.add("inetOrgPerson"); attrsbu.put(objclassSet); attrsbu.put("sn", account); attrsbu.put("uid", account); attrsbu.put("userPassword", password); ctx.createSubcontext("cn=" + account + ",ou=People", attrsbu); ctx.close(); return true; } catch (NamingException ex) { try { if (ctx != null) { ctx.close(); } } catch (NamingException namingException) { namingException.printStackTrace(); } logger.info("--------->>添加用户失败"); } return false; } // 修改密码 public static boolean updatePasswordLdap(String account, String password) { boolean success = false; try { ctx = LdapUtil.getLoginContext(); ModificationItem[] modificationItem = new ModificationItem[1]; modificationItem[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute("userPassword", password)); ctx.modifyAttributes("cn=" + account + ",ou=People", modificationItem); ctx.close(); return true; } catch (NamingException ex) { try { if (ctx != null) { ctx.close(); } } catch (NamingException namingException) { namingException.printStackTrace(); } logger.info("--------->>修改密码失败"); } return success; } // 删除用户 public static boolean deleteUserLdap(String account) { try { ctx = LdapUtil.getLoginContext(); ctx.destroySubcontext("cn=" + account); } catch (Exception ex) { try { if (ctx != null) { ctx.close(); } } catch (NamingException namingException) { namingException.printStackTrace(); } logger.info("--------->>删除用户失败"); return false; } return true; } // 关闭LDAP服务器连接 public static void closeCtx() { try { ctx.close(); } catch (NamingException ex) { logger.info("--------->> 关闭LDAP连接失败"); } } }
声明:以上教程为博主原创,若需转载请注明出处,谢谢。