dotNET Core 中怎样操作 AD?
做企業(yè)應(yīng)用開(kāi)發(fā)難免會(huì)跟 AD 打交道,在之前的 dotNET FrameWork 時(shí)代,通常使用 System.DirectoryServices 的相關(guān)類來(lái)操作 AD ,在 dotNET Core 中沒(méi)有這個(gè)命名空間,在張善友大佬的推薦下,知道了 Novell.Directory.Ldap。
操作 AD,通常有兩種常見(jiàn)的場(chǎng)景:
將第三方數(shù)據(jù)源數(shù)據(jù)(人事系統(tǒng))同步到 AD 中
將 AD 數(shù)據(jù)同步到自己的數(shù)據(jù)庫(kù)中
本文將介紹在 dotNET Core 中使用 Novell.Directory.Ldap 將 AD 數(shù)據(jù)同步到數(shù)據(jù)庫(kù)的操作。
環(huán)境
dotNET Core:2.1
Novell.Directory.Ldap.NETStandard2_0:3.1.0
安裝 Novell.Directory.Ldap 包
在 VS2019 中添加 NuGet 包引用,如下圖:
安裝完成后,在類中添加using Novell.Directory.Ldap;引用便可使用相關(guān)的 API 方法了。
同步思路
1、連接 AD
基本操作
同步方法
public?bool?Sync() {ADConnect();if?(_connection?==?null){throw?new?Exception("AD連接錯(cuò)誤,請(qǐng)確認(rèn)AD相關(guān)信息配置正確!");}bool?result?=?true;List<LdapEntry>?entryList?=?this.GetRootEntries(_adPaths,?_adHost);_org?=?new?Org();_user?=?new?User();Org?rootOrg?=?_org.GetRootOrg();foreach?(LdapEntry?entry?in?entryList){SyncDirectoryEntry(entry,?rootOrg,?entry);}return?result; }連接 AD
public?bool?ADConnect() {_adHost?=?"192.168.16.160";string?adAdminUserName?=?"administrator";string?adAdminPassword?=?"123456";_adPaths?=new?string[]?{?"OU=oec2003,DC=COM,DC=cn"?};if?((string.IsNullOrEmpty(_adHost)?||?string.IsNullOrEmpty(adAdminUserName))?||string.IsNullOrEmpty(adAdminPassword)){return?false;}try{_connection?=?new?LdapConnection();_connection.Connect(_adHost,?LdapConnection.DEFAULT_PORT);_connection.Bind(adAdminUserName,?adAdminPassword);}catch{return?false;}return?true; }遞歸操作
private?void?SyncDirectoryEntry(LdapEntry?rootEntry,?Org?parentOrg,?LdapEntry?currentEntry) {List<LdapEntry>?entryList?=?currentEntry.Children(_connection);foreach?(LdapEntry?entry?in?entryList){if?(entry.IsOrganizationalUnit()){Org?org?=?this.SyncOrgFromEntry(rootEntry,?parentOrg,?entry);this.SyncDirectoryEntry(rootEntry,?org,?entry);}else?if?(entry.IsUser()){this.SyncUserFromEntry(rootEntry,?parentOrg,?entry);}} }同步部門
private?Org?SyncOrgFromEntry(LdapEntry?rootEntry,?Org?parentOrg,?LdapEntry?entry) {string?orgId?=?entry.Guid().ToLower();Org?org?=?this._org.GetOrgById(orgId)?as?Org;if?(org?!=?null){if?(entry.ContainsAttr("ou")){org.Name?=?entry.getAttribute("ou").StringValue?+?string.Empty;}//設(shè)置其他屬性的值_org.UpdateOrg(org);return?org;}org?=?new?Org{Id?=?orgId,ParentId?=?parentOrg.Id,};//設(shè)置其他屬性的值this._org.AddOrg(org);return?org; }同步用戶
private?User?SyncUserFromEntry(LdapEntry?rootEntry,?Org?parentOrg,?LdapEntry?entry) {string?userId?=?entry.Guid().ToLower();User?user?=?this._user.GetUserById(userId);if?(user?!=?null){user.ParentId?=?parentOrg.Id;//設(shè)置其他屬性的值this._user.UpdateUser(user);return?user;}user?=?new?User{Id?=?userId,ParentId?=?parentOrg.Id};//設(shè)置其他屬性的值this._user.AddUser(user);return?user; }輔助方法
為了方便代碼的編寫(xiě)和復(fù)用,將一些操作提取到了擴(kuò)展方法中。
獲取 Entry 的 GUID
public?static?string?Guid(this?LdapEntry?entry) {var?bytes?=?(byte[])(entry.getAttribute("objectGUID").ByteValue?as?object);var?guid?=?new?Guid(bytes);return?guid.ToString(); }獲取 Entry 的 子級(jí)
public?static?List<LdapEntry>?Children(this?LdapEntry?entry,?LdapConnection?connection) {//string?filter?=?"(&(objectclass=user))";List<LdapEntry>?entryList?=?new?List<LdapEntry>();LdapSearchResults?lsc?=?connection.Search(entry.DN,?LdapConnection.SCOPE_ONE,?"objectClass=*",?null,?false);if?(lsc?==?null)?return?entryList;while?(lsc.HasMore()){LdapEntry?nextEntry?=?null;try{nextEntry?=?lsc.Next();if?(nextEntry.IsUser()?||?nextEntry.IsOrganizationalUnit()){entryList.Add(nextEntry);}}catch?(LdapException?e){continue;}}return?entryList; }判斷 Entry 是否為用戶
public?static?bool?IsUser(this?LdapEntry?entry) {return?entry.ObjectClass().Contains("user"); }判斷 Entry 是否為部門
public?static?bool?IsOrganizationalUnit(this?LdapEntry?entry) {return?entry.ObjectClass().Contains("organizationalunit"); }獲取 Entry 的修改時(shí)間
public?static?DateTime?WhenChanged(this?LdapEntry?entry) {string?value?=?entry.getAttribute("whenChanged").StringValue;if?(value.Split('.').Length?>?1){value?=?value.Split('.')[0];}DateTime?whenChanged?=?DateTime.ParseExact(value,?"yyyyMMddHHmmss",?System.Globalization.CultureInfo.CurrentCulture);return?whenChanged; }判斷 Entry 中屬性是否存在
public?static?bool?ContainsAttr(this?LdapEntry?entry,?string?attrName) {LdapAttribute?ldapAttribute?=?new?LdapAttribute(attrName);return?entry.getAttributeSet().Contains(ldapAttribute); }根據(jù)名稱獲取 Entry 中的屬性值
public?static?string?AttrStringValue(this?LdapEntry?entry,?string?attrName) {if?(!entry.ContainsAttr(attrName)){return?string.Empty;}return?entry.getAttribute(attrName).StringValue; }總結(jié)
文中沒(méi)有做更多文字性的介紹,可以從下面鏈接中下載代碼進(jìn)行調(diào)試就很容易理解了。
參考
示例代碼:https://github.com/oec2003/StudySamples/tree/master/DotNetCoreAdDemo/DotNetCoreAdDemo
祝大家國(guó)慶假期快樂(lè)!
總結(jié)
以上是生活随笔為你收集整理的dotNET Core 中怎样操作 AD?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
                            
                        - 上一篇: Kubernetes攻略之新手上路
 - 下一篇: 在树莓派4上安装 .NET Core 3