示例准備 |
- 打開上一篇文章配置好的AD域控制器
- 開始菜單-->管理工具-->Active Directory 用戶和計算機
- 新建組織單位和用戶
- 新建層次關系如下:
知識了解 |
我們要用C#訪問Active Directory非常容易,主要用到
System.DirectoryServices命名空間下的兩個組件類
讀取AD域信息示例 |
示例在Framework 3.5下用Winform程序編寫
主要結合常見需求讀取組織單位(OU)及用戶(User)信息,以及同步組織單位和用戶的層次關系;
比較着重的還是用戶的信息,特別是帳號、郵箱、SID等信息;
首先編寫代碼用LDAP嘗試對域進行訪問
形式:LDAP://Domain
#region## 是否連接到域 /// <summary> /// 功能:是否連接到域 /// 作者:Wilson /// 時間:2012-12-15 /// http://msdn.microsoft.com/zh-cn/library/system.directoryservices.directoryentry.path(v=vs.90).aspx /// </summary> /// <param name="domainName">域名或IP</param> /// <param name="userName">用戶名</param> /// <param name="userPwd">密碼</param> /// <param name="entry">域</param> /// <returns></returns> private bool IsConnected(string domainName, string userName, string userPwd, out DirectoryEntry domain) { domain = new DirectoryEntry(); try { domain.Path = string.Format("LDAP://{0}", domainName); domain.Username = userName; domain.Password = userPwd; domain.AuthenticationType = AuthenticationTypes.Secure; domain.RefreshCache(); return true; } catch(Exception ex) { LogRecord.WriteLog("[IsConnected方法]錯誤信息:" + ex.Message); return false; } } #endregion傳用參數,調IsConnected方法,結果如下
- 連接上AD域后,接着我們找到根OU
#region## 域中是否存在組織單位 /// <summary> /// 功能:域中是否存在組織單位 /// 作者:Wilson /// 時間:2012-12-15 /// </summary> /// <param name="entry"></param> /// <param name="ou"></param> /// <returns></returns> private bool IsExistOU(DirectoryEntry entry, out DirectoryEntry ou) { ou = new DirectoryEntry(); try { ou = entry.Children.Find("OU=" + txtRootOU.Text.Trim()); return (ou != null); } catch(Exception ex) { LogRecord.WriteLog("[IsExistOU方法]錯誤信息:" + ex.Message); return false; } } #endregion傳入以數,調用IsExistOU方法,結果如下
- 下面來開始讀取組織單位及用戶的信息。
示例為了看出層次關系及導出信息是類型區分,給OU和User新建了一個實體類和一個類型的枚舉
#region## 類型 /// <summary> /// 類型 /// </summary> public enum TypeEnum : int { /// <summary> /// 組織單位 /// </summary> OU = 1, /// <summary> /// 用戶 /// </summary> USER = 2 } #endregion #region## Ad域信息實體 /// <summary> /// Ad域信息實體 /// </summary> public class AdModel { public AdModel(string id, string name, int typeId, string parentId) { Id = id; Name = name; TypeId = typeId; ParentId = parentId; } public string Id { get; set; } public string Name { get; set; } public int TypeId { get; set; } public string ParentId { get; set; } } #endregion下面讀取信息
private List<AdModel> list = new List<AdModel>();
#region## 同步 /// <summary> /// 功能:同步 /// 創建人:Wilson /// 創建時間:2012-12-15 /// </summary> /// <param name="entryOU"></param> public void SyncAll(DirectoryEntry entryOU) { DirectorySearcher mySearcher = new DirectorySearcher(entryOU, "(objectclass=organizationalUnit)"); //查詢組織單位 DirectoryEntry root = mySearcher.SearchRoot; //查找根OU SyncRootOU(root); StringBuilder sb = new StringBuilder(); sb.Append("\r\nID\t帳號\t類型\t父ID\r\n"); foreach (var item in list) { sb.AppendFormat("{0}\t{1}\t{2}\t{3}\r\n", item.Id, item.Name, item.TypeId, item.ParentId); } LogRecord.WriteLog(sb.ToString()); MessageBox.Show("同步成功", this.Text, MessageBoxButtons.OK, MessageBoxIcon.Information); Application.Exit(); } #endregion #region## 同步根組織單位 /// <summary> /// 功能: 同步根組織單位 /// 創建人:Wilson /// 創建時間:2012-12-15 /// </summary> /// <param name="entry"></param> private void SyncRootOU(DirectoryEntry entry) { if (entry.Properties.Contains("ou") && entry.Properties.Contains("objectGUID")) { string rootOuName = entry.Properties["ou"][0].ToString(); byte[] bGUID = entry.Properties["objectGUID"][0] as byte[]; string id = BitConverter.ToString(bGUID); list.Add(new AdModel(id, rootOuName, (int)TypeEnum.OU, "0")); SyncSubOU(entry, id); } } #endregion #region## 同步下屬組織單位及下屬用戶 /// <summary> /// 功能: 同步下屬組織單位及下屬用戶 /// 創建人:Wilson /// 創建時間:2012-12-15 /// </summary> /// <param name="entry"></param> /// <param name="parentId"></param> private void SyncSubOU(DirectoryEntry entry, string parentId) { foreach (DirectoryEntry subEntry in entry.Children) { string entrySchemaClsName = subEntry.SchemaClassName; string[] arr = subEntry.Name.Split('='); string categoryStr = arr[0]; string nameStr = arr[1]; string id = string.Empty; if (subEntry.Properties.Contains("objectGUID")) //SID { byte[] bGUID = subEntry.Properties["objectGUID"][0] as byte[]; id = BitConverter.ToString(bGUID); } bool isExist = list.Exists(d => d.Id == id); switch (entrySchemaClsName) { case "organizationalUnit": if (!isExist) { list.Add(new AdModel(id, nameStr, (int)TypeEnum.OU, parentId)); } SyncSubOU(subEntry, id); break; case "user": string accountName = string.Empty; if (subEntry.Properties.Contains("samaccountName")) { accountName = subEntry.Properties["samaccountName"][0].ToString(); } if (!isExist) { list.Add(new AdModel(id, accountName, (int)TypeEnum.USER, parentId)); } break; } } } #endregion調用SyncAll方法循環輸出list,結果如下,很清楚的可以看出層次關系
//ID 帳號 類型 父ID //58-D6-C4-32-6A-A1-99-48-A4-8B-C8-5D-BC-C9-3E-17 acompany 1 0 //FB-44-91-AE-AC-73-2B-4D-9F-01-B1-E2-16-D3-CB-1B department01 1 58-D6-C4-32-6A-A1-99-48-A4-8B-C8-5D-BC-C9-3E-17 //47-9D-5B-91-60-22-D1-46-B0-CD-C7-B2-C7-D3-00-31 department03 1 FB-44-91-AE-AC-73-2B-4D-9F-01-B1-E2-16-D3-CB-1B //E3-AD-47-45-38-64-02-4D-B9-83-2C-50-67-50-4F-92 zw 2 47-9D-5B-91-60-22-D1-46-B0-CD-C7-B2-C7-D3-00-31 //8A-D4-23-18-F3-6F-E1-47-93-7A-CC-07-76-4B-E7-86 zhongw 2 FB-44-91-AE-AC-73-2B-4D-9F-01-B1-E2-16-D3-CB-1B //BC-D0-34-85-67-2F-05-4D-B5-77-E3-F4-AD-51-45-02 department02 1 58-D6-C4-32-6A-A1-99-48-A4-8B-C8-5D-BC-C9-3E-17 //1C-13-FA-66-E4-51-65-49-8B-DC-22-60-32-34-8F-22 wilson 2 BC-D0-34-85-67-2F-05-4D-B5-77-E3-F4-AD-51-45-02 //84-E8-E5-9A-6B-56-E2-45-9A-87-54-D1-78-6B-D3-56 porschev 2 58-D6-C4-32-6A-A1-99-48-A4-8B-C8-5D-BC-C9-3E-17
DirectorySearcher.Filter屬性擴充說明 |
DirectorySearcher mySearcher = new DirectorySearcher(entryOU, "(objectclass=organizationalUnit)"); //查詢組織單位
第二個參數是一個filter,也可以根據需求輸入其它篩選條件,下面列出幾個常用的
篩選條件 值 用戶 (&(objectCategory=person)(objectClass=user)) 計算機 (objectCategory=computer) 組 (objectCategory=group) 聯系人 (objectCategory=contact) 共享文件夾 (objectCategory=volume) 打印機 (objectCategory=printQueue)
用戶屬性擴充說明(含圖文屬性對照) |
示例中只對用戶進行了讀取了幾個屬性,用過AD域的應該都知道,用戶的屬性較多也比較常用。
下面通過AD域的用戶詳細信來對照一下相應的屬性名
對應編號 選項卡對應項名 屬性名 ① 姓(L) sn ② 名(F) givenName ③ 顯示名稱(S) displayName ④ 描述(D) description ⑤ 辦公室(C) physicalDeliveryOfficeName ⑥ 英文縮寫(I) initials ⑦ 電話號碼(T) telephoneNumber ⑧ 電子郵件(M) ⑨ 網頁(W) wWWHomePage ⑩ 電話號碼-其它(O)... otherTelephone ⑪ 網頁-其它(R)... url
對應編號 選項卡對應項名 屬性名 ① 國家/地區(O) co ② 省/自治區(V) st ③ 市/縣(C) l ④ 街道(S) streetAddress ⑤ 郵政信箱(B) postOfficeBox ⑥ 郵政編碼(Z) postalCode
對應編號 選項卡對應項名 屬性名 ① 用戶登錄名(U) userPrincipalName ② 用戶登錄名(Windows 2000 以前版本)(W) sAMAccountName
對應編號 選項卡對應項名 屬性名 ① 家庭電話(M) homePhone ② 尋呼機(P) pager ③ 移動電話(B) mobile ④ 傳真(F) facsimileTelephoneNumber ⑤ IP電話(I) ipPhone ⑥ 注釋 info ⑦ 家庭電話-其它(O) otherHomePhone ⑧ 尋呼機-其它(T) otherPager ⑨ 移動電話-其它(B) otherMobile ⑩ 傳真-其它(E) otherFacsimileTelephoneNumber ⑪ IP電話-其它(R) otherIpPhone
對應編號 選項卡對應項名 屬性名 ① 公司(C) company ② 部門(D) department ③ 職務(J) title ④ 經理-姓名(N) manager ⑥ 直接下屬(E) directReports
還有一些屬性沒有列出來,可以循環輸出DirectoryEntry.Properties.PropertyNames來找
比如用objectsid這也是個用戶比較重要的屬性,在設置Windows共享時會用到!