項(xiàng)目上遇到的需要在集成 操作域用戶的信息的功能,第一次接觸ad域,因?yàn)椴涣私舛揖W(wǎng)上其他介紹不明確,比較費(fèi)時(shí),這里記錄下。
創(chuàng)新互聯(lián)是一家專業(yè)提供清流企業(yè)網(wǎng)站建設(shè),專注與成都網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè)、H5頁面制作、小程序制作等業(yè)務(wù)。10年已為清流眾多企業(yè)、政府機(jī)構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專業(yè)網(wǎng)站建設(shè)公司優(yōu)惠進(jìn)行中。
說明:
(1). 特別注意:Java操作查詢域用戶信息獲取到的數(shù)據(jù)和域管理員在電腦上操作查詢的數(shù)據(jù)可能會存在差異(同一個(gè)意思的表示字段,兩者可能不同)。
(2). 連接ad域有兩個(gè)地址: ldap://XXXXX.com:389 和 ldap://XXXXX.com:636(SSL)。
(3). 端口389用于一般的連接,例如登錄,查詢等非密碼操作,端口636安全性較高,用戶密碼相關(guān)操作,例如修改密碼等。
(4). 域控可能有多臺服務(wù)器,之間數(shù)據(jù)同步不及時(shí),可能會導(dǎo)致已經(jīng)修改的數(shù)據(jù)被覆蓋掉,這個(gè)要么域控縮短同步的時(shí)間差,要么同時(shí)修改每一臺服務(wù)器的數(shù)據(jù)。
1. 389登錄
// 只要不拋出異常就是驗(yàn)證通過 public LdapContext adLogin(JSONObject json) { String username = json.getString("username"); String password = json.getString("password"); String server = "ldap://XXXXXXX.com:389"; try { Hashtable<String, String> env = new Hashtable<String, String>(); //用戶名稱,cn,ou,dc 分別:用戶,組,域 env.put(Context.SECURITY_PRINCIPAL, username); //用戶密碼 cn 的密碼 env.put(Context.SECURITY_CREDENTIALS, password); //url 格式:協(xié)議://ip:端口/組,域 ,直接連接到域或者組上面 env.put(Context.PROVIDER_URL, server); //LDAP 工廠 env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); //驗(yàn)證的類型 "none", "simple", "strong" env.put(Context.SECURITY_AUTHENTICATION, "simple"); LdapContext ldapContext = new InitialLdapContext(env, null); log.info("ldapContext:" + ldapContext); log.info("用戶" + username + "登錄驗(yàn)證成功"); return ldapContext; } catch (NamingException e) { log.info("用戶" + username + "登錄驗(yàn)證失敗"); log.info("錯(cuò)誤信息:"+e.getExplanation()); return null; } }
2. 636登錄驗(yàn)證(需要導(dǎo)入證書)
//證書提前倒入的Java庫中 // 參考:https://www.cnblogs.com/moonson/p/4454159.html LdapContext adLoginSSL(JSONObject json) { String username = json.getString("username"); String password = json.getString("password"); Hashtable env = new Hashtable(); String javaHome = System.getProperty("java.home"); String keystore = javaHome+"/lib/security/cacerts"; log.info("java.home,{}",keystore); // 加載導(dǎo)入jdk的域證書 System.setProperty("javax.net.ssl.trustStore", keystore); System.setProperty("javax.net.ssl.trustStorePassword", "changeit"); String LDAP_URL = "ldap://XXXXXX.com:636"; // LDAP訪問地址 env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.SECURITY_PROTOCOL, "ssl");//鏈接認(rèn)證服務(wù)器 env.put(Context.PROVIDER_URL, LDAP_URL); env.put(Context.SECURITY_AUTHENTICATION, "simple"); env.put(Context.SECURITY_PRINCIPAL, username); env.put(Context.SECURITY_CREDENTIALS, password); try { LdapContext ldapContext = new InitialLdapContext(env, null); log.info("認(rèn)證成功");// 這里可以改成異常拋出。 return ldapContext; } catch (javax.naming.AuthenticationException e) { log.info("認(rèn)證失敗:{}",e.getMessage()); } catch (Exception e) { log.info("認(rèn)證出錯(cuò):{}",e.getMessage()); } return null; }
3. 查詢域用戶信息
public List getUserKey(JSONObject json){ JSONObject admin = new JSONObject(); admin.put("username","Aaaaa"); admin.put("password", "bbbbbbbb"); String name = json.getString("name"); log.info("需要查詢的ad信息:{}",name); List<JSONObject> resultList = new JSONArray(); LdapContext ldapContext = adLogin(admin); //連接到域控 if (ldapContext!=null){ String company = ""; String result = ""; try { // 域節(jié)點(diǎn) String searchBase = "DC=XXXXXXX,DC=com"; // LDAP搜索過濾器類 //cn=*name*模糊查詢 //cn=name 精確查詢 // String searchFilter = "(objectClass="+type+")"; String searchFilter = "(sAMAccountName="+name+")"; //查詢域帳號 // 創(chuàng)建搜索控制器 SearchControls searchCtls = new SearchControls(); String returnedAtts[]={"description","sAMAccountName","userAccountControl"}; searchCtls.setReturningAttributes(returnedAtts); //設(shè)置指定返回的字段,不設(shè)置則返回全部 // 設(shè)置搜索范圍 深度 searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE); // 根據(jù)設(shè)置的域節(jié)點(diǎn)、過濾器類和搜索控制器搜索LDAP得到結(jié)果 NamingEnumeration answer = ldapContext.search(searchBase, searchFilter,searchCtls); // 初始化搜索結(jié)果數(shù)為0 int totalResults = 0; int rows = 0; while (answer.hasMoreElements()) {// 遍歷結(jié)果集 SearchResult sr = (SearchResult) answer.next();// 得到符合搜索條件的DN ++rows; String dn = sr.getName(); log.info(dn); Attributes Attrs = sr.getAttributes();// 得到符合條件的屬性集 if (Attrs != null) { try { for (NamingEnumeration ne = Attrs.getAll(); ne.hasMore();) { Attribute Attr = (Attribute) ne.next();// 得到下一個(gè)屬性 // 讀取屬性值 for (NamingEnumeration e = Attr.getAll(); e.hasMore(); totalResults++) { company = e.next().toString(); JSONObject tempJson = new JSONObject(); tempJson.put(Attr.getID(), company.toString()); resultList.add(tempJson); } } } catch (NamingException e) { log.info("Throw Exception : " + e.getMessage()); } } } log.info("總共用戶數(shù):" + rows); } catch (NamingException e) { log.info("Throw Exception : " + e.getMessage()); }finally { try{ ldapContext.close(); }catch (Exception e){ e.printStackTrace(); } } } return resultList; }
4. 重置用戶密碼
// 管理員重置用戶密碼,后強(qiáng)制用戶首次登錄修改密碼 public Map<String, String> updateAdPwd(JSONObject json) { String dn = json.getString("dn");//要修改的帳號(這個(gè)dn是查詢的用戶信息里的dn的值,而不是域賬號) String password = json.getString("password");//新密碼 JSONObject admin = new JSONObject(); admin.put("username","aaaaaaa"); admin.put("password", "bbbbbbb"); Map<String,String> map = new HashMap<String,String>(); LdapContext ldapContext = adLoginSSL(admin); //連接636端口域 ModificationItem[] mods = new ModificationItem[2]; if (ldapContext!=null){ try { String newQuotedPassword = "\"" + password + "\""; byte[] newUnicodePassword = newQuotedPassword.getBytes("UTF-16LE"); // unicodePwd:修改的字段,newUnicodePassword:修改的值 mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute("unicodePwd", newUnicodePassword)); mods[1] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute("pwdLastSet", "0")); // 首次登錄必須修改密碼 // 修改密碼 ldapContext.modifyAttributes(dn, mods); map.put("result", "S"); map.put("message","成功"); }catch (Exception e){ map.put("result","E"); map.put("message", "無法重置密碼"); }finally { try{ ldapContext.close(); }catch (Exception e){ e.printStackTrace(); } } }else { log.info(""); map.put("result","E"); map.put("message", "驗(yàn)證失敗"); } return map; }
5. 域賬號解鎖
// 表示鎖定的字段需要測試,不一定這個(gè)lockoutTime public Map<String, String> deblocking(JSONObject json) { JSONObject admin = new JSONObject(); String dn = json.getString("dn"); //被解鎖的帳號(這個(gè)dn指的是查詢用戶信息里的dn的值,不是域賬號) admin.put("username","aaaaaa"); admin.put("password","bbbbbb"); Map<String,String> map = new HashMap<String,String>(); LdapContext ldapContext = adLogin(admin); ModificationItem[] mods = new ModificationItem[1]; if (ldapContext!=null){ try { // "0" 表示未鎖定,不為0表示鎖定 mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute("lockoutTime","0")); // 解鎖域帳號 ldapContext.modifyAttributes(dn, mods); map.put("result", "S"); map.put("message","成功"); }catch (Exception e){ map.put("result","E"); map.put("message", "解鎖失敗"); }finally { try{ ldapContext.close(); }catch (Exception e){ e.printStackTrace(); } } }else { map.put("result","E"); map.put("message", "驗(yàn)證失敗"); } return map; }
Java通過Ldap操作AD的增刪改查詢
package com.smnpc.util; import java.util.Hashtable; import java.util.Vector; 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.BasicAttribute; import javax.naming.directory.BasicAttributes; import javax.naming.directory.DirContext; import javax.naming.directory.InitialDirContext; import javax.naming.directory.ModificationItem; import javax.naming.directory.SearchControls; import javax.naming.directory.SearchResult; import javax.naming.ldap.LdapContext; /** * Java通過Ldap操作AD的增刪該查詢 * @author guob */ public class LdapbyUser { DirContext dc = null; String root = "dc=example,dc=com"; // LDAP的根節(jié)點(diǎn)的DC /** * * @param dn類似于"CN=RyanHanson,dc=example,dc=com" * @param employeeID是Ad的一個(gè)員工號屬性 */ public LdapbyUser(String dn,String employeeID) { init(); // add();//添加節(jié)點(diǎn) // delete("ou=hi,dc=example,dc=com");//刪除"ou=hi,dc=example,dc=com"節(jié)點(diǎn) // renameEntry("ou=new,o=neworganization,dc=example,dc=com","ou=neworganizationalUnit,o=neworganization,dc=example,dc=com");//重命名節(jié)點(diǎn)"ou=new,o=neworganization,dc=example,dc=com" // searchInformation("dc=example,dc=com", "", "sAMAccountName=guob");//遍歷所有根節(jié)點(diǎn) modifyInformation(dn,employeeID);//修改 // Ldapbyuserinfo("guob");//遍歷指定節(jié)點(diǎn)的分節(jié)點(diǎn) close(); } /** * * Ldap連接 * * @return LdapContext */ public void init() { Hashtable env = new Hashtable(); String LDAP_URL = "ldap://xxxx:389"; // LDAP訪問地址 String adminName = "example\\user"; // 注意用戶名的寫法:domain\User或 String adminPassword = "userpassword"; // 密碼 env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.PROVIDER_URL, LDAP_URL); env.put(Context.SECURITY_AUTHENTICATION, "simple"); env.put(Context.SECURITY_PRINCIPAL, adminName); env.put(Context.SECURITY_CREDENTIALS, adminPassword); try { dc = new InitialDirContext(env);// 初始化上下文 System.out.println("認(rèn)證成功");// 這里可以改成異常拋出。 } catch (javax.naming.AuthenticationException e) { System.out.println("認(rèn)證失敗"); } catch (Exception e) { System.out.println("認(rèn)證出錯(cuò):" + e); } } /** * 添加 */ public void add(String newUserName) { try { BasicAttributes attrs = new BasicAttributes(); BasicAttribute objclassSet = new BasicAttribute("objectClass"); objclassSet.add("sAMAccountName"); objclassSet.add("employeeID"); attrs.put(objclassSet); attrs.put("ou", newUserName); dc.createSubcontext("ou=" + newUserName + "," + root, attrs); } catch (Exception e) { e.printStackTrace(); System.out.println("Exception in add():" + e); } } /** * 刪除 * * @param dn */ public void delete(String dn) { try { dc.destroySubcontext(dn); } catch (Exception e) { e.printStackTrace(); System.out.println("Exception in delete():" + e); } } /** * 重命名節(jié)點(diǎn) * * @param oldDN * @param newDN * @return */ public boolean renameEntry(String oldDN, String newDN) { try { dc.rename(oldDN, newDN); return true; } catch (NamingException ne) { System.err.println("Error: " + ne.getMessage()); return false; } } /** * 修改 * * @return */ public boolean modifyInformation(String dn,String employeeID) { try { System.out.println("updating...\n"); ModificationItem[] mods = new ModificationItem[1]; /* 修改屬性 */ // Attribute attr0 = new BasicAttribute("employeeID", "W20110972"); // mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, attr0); /* 刪除屬性 */ // Attribute attr0 = new BasicAttribute("description", // "陳軼"); // mods[0] = new ModificationItem(DirContext.REMOVE_ATTRIBUTE, // attr0); /* 添加屬性 */ Attribute attr0 = new BasicAttribute("employeeID",employeeID); mods[0] = new ModificationItem(DirContext.ADD_ATTRIBUTE, attr0); /* 修改屬性 */ dc.modifyAttributes(dn+",dc=example,dc=com", mods); return true; } catch (NamingException e) { e.printStackTrace(); System.err.println("Error: " + e.getMessage()); return false; } } /** * 關(guān)閉Ldap連接 */ public void close() { if (dc != null) { try { dc.close(); } catch (NamingException e) { System.out.println("NamingException in close():" + e); } } } /** * @param base :根節(jié)點(diǎn)(在這里是"dc=example,dc=com") * @param scope :搜索范圍,分為"base"(本節(jié)點(diǎn)),"one"(單層),""(遍歷) * @param filter :指定子節(jié)點(diǎn)(格式為"(objectclass=*)",*是指全部,你也可以指定某一特定類型的樹節(jié)點(diǎn)) */ public void searchInformation(String base, String scope, String filter) { SearchControls sc = new SearchControls(); if (scope.equals("base")) { sc.setSearchScope(SearchControls.OBJECT_SCOPE); } else if (scope.equals("one")) { sc.setSearchScope(SearchControls.ONELEVEL_SCOPE); } else { sc.setSearchScope(SearchControls.SUBTREE_SCOPE); } NamingEnumeration ne = null; try { ne = dc.search(base, filter, sc); // Use the NamingEnumeration object to cycle through // the result set. while (ne.hasMore()) { System.out.println(); SearchResult sr = (SearchResult) ne.next(); String name = sr.getName(); if (base != null && !base.equals("")) { System.out.println("entry: " + name + "," + base); } else { System.out.println("entry: " + name); } Attributes at = sr.getAttributes(); NamingEnumeration ane = at.getAll(); while (ane.hasMore()) { Attribute attr = (Attribute) ane.next(); String attrType = attr.getID(); NamingEnumeration values = attr.getAll(); Vector vals = new Vector(); // Another NamingEnumeration object, this time // to iterate through attribute values. while (values.hasMore()) { Object oneVal = values.nextElement(); if (oneVal instanceof String) { System.out.println(attrType + ": " + (String) oneVal); } else { System.out.println(attrType + ": " + new String((byte[]) oneVal)); } } } } } catch (Exception nex) { System.err.println("Error: " + nex.getMessage()); nex.printStackTrace(); } } /** * 查詢 * * @throws NamingException */ public void Ldapbyuserinfo(String userName) { // Create the search controls SearchControls searchCtls = new SearchControls(); // Specify the search scope searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE); // specify the LDAP search filter String searchFilter = "sAMAccountName=" + userName; // Specify the Base for the search 搜索域節(jié)點(diǎn) String searchBase = "DC=example,DC=COM"; int totalResults = 0; String returnedAtts[] = { "url", "whenChanged", "employeeID", "name", "userPrincipalName", "physicalDeliveryOfficeName", "departmentNumber", "telephoneNumber", "homePhone", "mobile", "department", "sAMAccountName", "whenChanged", "mail" }; // 定制返回屬性 searchCtls.setReturningAttributes(returnedAtts); // 設(shè)置返回屬性集 // searchCtls.setReturningAttributes(null); // 不定制屬性,將返回所有的屬性集 try { NamingEnumeration answer = dc.search(searchBase, searchFilter, searchCtls); if (answer == null || answer.equals(null)) { System.out.println("answer is null"); } else { System.out.println("answer not null"); } while (answer.hasMoreElements()) { SearchResult sr = (SearchResult) answer.next(); System.out .println("************************************************"); System.out.println("getname=" + sr.getName()); Attributes Attrs = sr.getAttributes(); if (Attrs != null) { try { for (NamingEnumeration ne = Attrs.getAll(); ne .hasMore();) { Attribute Attr = (Attribute) ne.next(); System.out.println("AttributeID=" + Attr.getID().toString()); // 讀取屬性值 for (NamingEnumeration e = Attr.getAll(); e .hasMore(); totalResults++) { String user = e.next().toString(); // 接受循環(huán)遍歷讀取的userPrincipalName用戶屬性 System.out.println(user); } // System.out.println(" ---------------"); // // 讀取屬性值 // Enumeration values = Attr.getAll(); // if (values != null) { // 迭代 // while (values.hasMoreElements()) { // System.out.println(" 2AttributeValues=" // + values.nextElement()); // } // } // System.out.println(" ---------------"); } } catch (NamingException e) { System.err.println("Throw Exception : " + e); } } } System.out.println("Number: " + totalResults); } catch (Exception e) { e.printStackTrace(); System.err.println("Throw Exception : " + e); } } /** * 主函數(shù)用于測試 * @param args */ public static void main(String[] args) { new LdapbyUser("CN=RyanHanson","bbs.it-home.org"); } }
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。
分享文章:JAVA使用Ldap操作AD域的方法示例
網(wǎng)頁網(wǎng)址:http://muchs.cn/article46/iegghg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站設(shè)計(jì)公司、服務(wù)器托管、網(wǎng)站改版、品牌網(wǎng)站建設(shè)、外貿(mào)網(wǎng)站建設(shè)、虛擬主機(jī)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)