Java程式通過LDAP對使用者進行登陸驗證
阿新 • • 發佈:2019-01-27
在去年南京專案中,客戶方要求使用者登陸需要在其他平臺下進行認證,當時客戶用的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連線失敗"); } } }
宣告:以上教程為博主原創,若需轉載請註明出處,謝謝。