dotNET Core 中怎样操作AD(续1)
在之前的文章《dotNET Core 中怎樣操作 AD?》中主要以AD的數(shù)據(jù)同步到數(shù)據(jù)庫的場景來描述了在 dotNetCore 中怎樣操作AD,本文將繼續(xù)介紹一些在 dotNetCore 中操作 AD 的其他常用操作。
環(huán)境
dotNET Core:3.0
Novell.Directory.Ldap.NETStandard2_0:3.1.0
AD:windows server 2012
基本操作
查詢
在 AD 中進(jìn)行用戶的操作,通常需要先判斷用戶是否存在,這時(shí)就需要使用查詢了,用下面代碼可以進(jìn)行 AD 中的查詢:
?var?entities?=?_connection.Search(ADClient.BaseDC,LdapConnection.SCOPE_SUB,$"sAMAccountName={loginName}",null,?false);參數(shù)說明:
base: 指定的總體搜索范圍,通常在創(chuàng)建連接時(shí)會(huì)指定一個(gè) BaseDC,表示后面的操作在此 DC 范圍內(nèi),如果希望從根開始搜索,此參數(shù)可傳空
scope:查詢遍歷的方式,分為 SCOPE_BASE 、SCOPE_ONE 和 SCOPE_SUB 三種
SCOPE_BASE:通常知道對(duì)象的 DN,并希望獲取其屬性時(shí),使用此項(xiàng)
SCOPE_ONE:查詢 base 的下一層級(jí)
SCOPE_SUB:查詢 base 下的所有對(duì)象,包含 base
filter:用來過濾的表達(dá)式,下面列出一些常用的表達(dá)式
(cn=oec2003):返回 cn 等于 oec2003 的用戶 (sAMAccountName=oec*):返回登錄名以 oec 開頭的用戶 !(cn=oec2003):返回 cn 不等于 oec2003 的用戶 (|(cn=oec2003)(telephonenumber=888*)):返回 cn 等于 oec2003 ,或者電話號(hào)碼以 888 開頭的用戶 (&(cn=oec2003)(telephonenumber=888*)):返回 cn 等于 oec2003 ,并且電話號(hào)碼以 888 開頭的用戶其他更多的表達(dá)式可以參考官方文檔:https://www.novell.com/documentation/developer/ldapcsharp/?page=/documentation/developer/ldapcsharp/cnet/data/bovtuda.html
attrs:字符串?dāng)?shù)組,可以指定返回的屬性的列表,不指定返回所有的屬性
例如根據(jù)登錄名來查詢用戶的示例代碼如下:
public?static?LdapEntry?GetUser(string?loginName) {var?entities?=?_connection.Search(ADClient.BaseDC,LdapConnection.SCOPE_SUB,$"sAMAccountName={loginName}",null,?false);LdapEntry?entry?=?null;while?(entities.HasMore()){try{entry?=?entities.Next();}catch?(LdapException?e){Console.WriteLine($"GetUser?Error:?{e.Message}");continue;}}return?entry; }添加用戶
public?static?bool?AddUser(string?userName,?string?loginName,?string?defaultPwd,?string?container) {//設(shè)置默認(rèn)密碼defaultPwd?=?$"\"{defaultPwd}\"";sbyte[]?encodedBytes?=?SupportClass.ToSByteArray(Encoding.Unicode.GetBytes(defaultPwd));LdapAttributeSet?attributeSet?=?new?LdapAttributeSet();attributeSet.Add(new?LdapAttribute("objectclass",?"user"));attributeSet.Add(new?LdapAttribute("sAMAccountName",?userName));//設(shè)置創(chuàng)建用戶后啟用attributeSet.Add(new?LdapAttribute("userAccountControl",?(66080).ToString()));attributeSet.Add(new?LdapAttribute("unicodePwd",?encodedBytes));string?dn?=?$"CN={loginName},{container}";LdapEntry?newEntry?=?new?LdapEntry(dn,?attributeSet);_connection.Add(newEntry);return?true; }注意點(diǎn):
默認(rèn)密碼的設(shè)置需要給密碼加上引號(hào)
默認(rèn)情況下創(chuàng)建的用戶是禁用的,如果要啟用需要加上代碼attributeSet.Add(new LdapAttribute("userAccountControl", (66080).ToString()));
修改密碼
public?static?bool?UpdatePassword(string?loginName,?string?password) {LdapEntry?entry?=?GetUser(loginName);if?(entry?==?null){throw?new?Exception($"名為:{loginName}?的用戶在AD中不存在");}password?=?$"\"{password}\"";sbyte[]?encodedBytes?=?SupportClass.ToSByteArray(Encoding.Unicode.GetBytes(password));LdapAttribute?attributePassword?=?new?LdapAttribute("unicodePwd",?encodedBytes);_connection.Modify(entry.DN,?new?LdapModification(LdapModification.REPLACE,?attributePassword));return?true; }禁用用戶
public?static?bool?EnblaedUser(string?loginName) {LdapEntry?entry?=?GetUser(loginName);if?(entry?==?null){throw?new?Exception($"名為:{loginName}?的用戶在AD中不存在");}LdapAttribute?attributePassword?=?new?LdapAttribute("userAccountControl",?(66082).ToString());_connection.Modify(entry.DN,?new?LdapModification(LdapModification.REPLACE,?attributePassword));return?true; }啟用用戶
public?static?bool?EnblaedUser(string?loginName) {LdapEntry?entry?=?GetUser(loginName);if?(entry?==?null){throw?new?Exception($"名為:{loginName}?的用戶在AD中不存在");}LdapAttribute?attributePassword?=?new?LdapAttribute("userAccountControl",?(66080).ToString());_connection.Modify(entry.DN,?new?LdapModification(LdapModification.REPLACE,?attributePassword));return?true; }移動(dòng)用戶到新的 OU
public?static?bool?MoveUserToOU(string?loginName,?string?rcn?=?"",?string?ouContainer?=?"") {LdapEntry?entry?=?GetUser(loginName);if?(entry?==?null){throw?new?Exception($"名為:{loginName}?的用戶在AD中不存在");}string?cn?=?entry.AttrStringValue("cn");cn?=?rcn?==?""???cn?:?rcn;string?newRCN?=?$"CN={cn}";if?(string.IsNullOrWhiteSpace(ouContainer)){_connection.Rename(entry.DN,?newRCN,?true);}else{_connection.Rename(entry.DN,?newRCN,?ouContainer,?true);}return?true; }注意點(diǎn):
一個(gè)用戶一旦創(chuàng)建,DN 是不能修改的,可以通過Rename方法來修改 CN 來達(dá)到修改 DN 的目的
如果傳入第三個(gè)參數(shù)ouContainer,就可以實(shí)現(xiàn)將用戶移動(dòng)到目標(biāo) OU
添加用戶到組
public?static?bool?AddUserToGroup(string?loginName,?string?groupDN) {LdapEntry?entry?=?GetUser(loginName);if?(entry?==?null){throw?new?Exception($"名為:{loginName}?的用戶在AD中不存在");}List<string>?memberOf?=?entry.AttrStringValueArray("memberOf");if?(memberOf.Contains(groupDN)){throw?new?Exception($"名為:{loginName}?的用戶已經(jīng)加入了組:?{groupDN}");}LdapModification[]?modGroup?=?new?LdapModification[1];LdapAttribute?member?=?new?LdapAttribute("member",?entry.DN);modGroup[0]?=?new?LdapModification(LdapModification.ADD,?member);try{_connection.Modify(groupDN,?modGroup);}catch?(LdapException?e){System.Console.Error.WriteLine("Failed?to?modify?group's?attributes:?"?+?e.LdapErrorMessage);return?false;}catch?(Exception?e){Console.Error.WriteLine("AddUserToGroup?Error:"?+?e.Message);return?false;}return?true; }用戶從組中移除
public?static?bool?RemoveUserFromGroup(string?loginName,?string?groupDN) {LdapEntry?entry?=?GetUser(loginName);if?(entry?==?null){throw?new?Exception($"名為:{loginName}?的用戶在AD中不存在");}List<string>?memberOf?=?entry.AttrStringValueArray("memberOf");if?(!memberOf.Contains(groupDN)){throw?new?Exception($"名為:{loginName}?的用戶不存在于組:?{groupDN}?中");}LdapModification[]?modGroup?=?new?LdapModification[1];LdapAttribute?member?=?new?LdapAttribute("member",?entry.DN);modGroup[0]?=?new?LdapModification(LdapModification.DELETE,?member);try{_connection.Modify(groupDN,?modGroup);}catch?(LdapException?e){System.Console.Error.WriteLine("Failed?to?delete?group's?attributes:?"?+?e.LdapErrorMessage);return?false;}catch?(Exception?e){Console.Error.WriteLine("RemoveUserFromGroup?Error:"?+?e.Message);return?false;}return?true; }添加用戶登錄到
public?static?bool?UpdateUserWorkStation(string?loginName,?string?computerName,?UserWorkStationOperType?type) {LdapEntry?entry?=?GetUser(loginName);if?(entry?==?null){throw?new?Exception($"名為:{loginName}?的用戶在AD中不存在");}List<string>?stations?=?entry.AttrStringValue("userWorkstations").Split(',').ToList();if?(type?==?UserWorkStationOperType.Add?&&?!stations.Contains(computerName)){stations.Add(computerName);}else?if?(type?==?UserWorkStationOperType.Remove?&&?stations.Contains(computerName)){stations.Remove(computerName);}LdapAttribute?attributePassword?=?new?LdapAttribute("userWorkstations",?string.Join(',',?stations));_connection.Modify(entry.DN,?new?LdapModification(LdapModification.REPLACE,?attributePassword));return?true; }最后
本文的示例代碼已推送到 GitHub:https://github.com/oec2003/DotNetCoreAdDemo
官網(wǎng)也有些示例,但不是很完善,而且有很多代碼并不能正常執(zhí)行(可能跟 AD 的版本有關(guān)),所以才有了本示例。本示例也會(huì)添加更多的使用場景,不斷完善。
希望本文對(duì)您有所幫助。
總結(jié)
以上是生活随笔為你收集整理的dotNET Core 中怎样操作AD(续1)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用 OAS(OpenAPI标准)来描述
- 下一篇: Elastic发布K8s部署和控制数据管