In the previous article how to operate AD "dotNET Core in? " Mainly to synchronize data AD to the scene database described in how to operate the AD dotNetCore herein will introduce some other common operations continue to operate in dotNetCore in AD.
surroundings
dotNET Core:3.0
Novell.Directory.Ldap.NETStandard2_0:3.1.0
AD:windows server 2012
Basic Operations
Inquire
User operation in AD, usually need to determine whether the user is present, then you need to use the query, the query may be performed in AD with the following codes:
var entities = _connection.Search(ADClient.BaseDC,LdapConnection.SCOPE_SUB,
$"sAMAccountName={loginName}",
null, false);
Parameter Description:
base: general search range specified, usually specify a BaseDC up a connection, the latter showing the operation within this range DC, if desired to start the search from the root, this parameter may be null passed
scope: Query traverse way into SCOPE_BASE, SCOPE_ONE and three kinds SCOPE_SUB
SCOPE_BASE: usually know when DN object and want to get their properties, use this
SCOPE_ONE: Query base next level
SCOPE_SUB: all the objects in the query base, containing base
filter: to filter expressions, the following expressions are some common
(cn=oec2003):返回 cn 等于 oec2003 的用户 (sAMAccountName=oec*):返回登录名以 oec 开头的用户 !(cn=oec2003):返回 cn 不等于 oec2003 的用户 (|(cn=oec2003)(telephonenumber=888*)):返回 cn 等于 oec2003 ,或者电话号码以 888 开头的用户 (&(cn=oec2003)(telephonenumber=888*)):返回 cn 等于 oec2003 ,并且电话号码以 888 开头的用户
Other more expressions can refer to the official document: https: //www.novell.com/documentation/developer/ldapcsharp/ page = / documentation / developer / ldapcsharp / cnet / data / bovtuda.html?
attrs: string array, may specify property returns a list of all attributes is not specified return
For example, according to the sample code to query the user's login name as follows:
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;
}
Add user
public static bool AddUser(string userName, string loginName, string defaultPwd, string container)
{
//设置默认密码
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));
//设置创建用户后启用
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;
}
important point:
Set the default password of password needed to add quotes
Created by the user is disabled by default, if you need to add the code to enable
attributeSet.Add(new LdapAttribute("userAccountControl", (66080).ToString()));
change Password
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;
}
Disable User
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;
}
Enable User
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;
}
Moving users to the new 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;
}
important point:
一个用户一旦创建,DN 是不能修改的,可以通过
Rename
方法来修改 CN 来达到修改 DN 的目的如果传入第三个参数
ouContainer
,就可以实现将用户移动到目标 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} 的用户已经加入了组: {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
官网也有些示例,但不是很完善,而且有很多代码并不能正常执行(可能跟 AD 的版本有关),所以才有了本示例。本示例也会添加更多的使用场景,不断完善。
希望本文对您有所帮助。