在之前的文章《dotNET Core 中怎样操作 AD?》中主要以AD的数据同步到数据库的场景来描述了在 dotNetCore 中怎样操作AD,本文将继续介绍一些在 dotNetCore 中操作 AD 的其他常用操作。

环境

  • dotNET Core:3.0

  • Novell.Directory.Ldap.NETStandard2_0:3.1.0

  • AD:windows server 2012

基本操作

查询

在 AD 中进行用户的操作,通常需要先判断用户是否存在,这时就需要使用查询了,用下面代码可以进行 AD 中的查询:

 var entities = _connection.Search(ADClient.BaseDC,LdapConnection.SCOPE_SUB,$"sAMAccountName={loginName}",null, false);

参数说明:

  • base: 指定的总体搜索范围,通常在创建连接时会指定一个 BaseDC,表示后面的操作在此 DC 范围内,如果希望从根开始搜索,此参数可传空

  • scope:查询遍历的方式,分为 SCOPE_BASE 、SCOPE_ONE 和 SCOPE_SUB 三种

    • SCOPE_BASE:通常知道对象的 DN,并希望获取其属性时,使用此项

    • SCOPE_ONE:查询 base 的下一层级

    • SCOPE_SUB:查询 base 下的所有对象,包含 base

  • filter:用来过滤的表达式,下面列出一些常用的表达式

    (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 开头的用户
    

    其他更多的表达式可以参考官方文档:https://www.novell.com/documentation/developer/ldapcsharp/?page=/documentation/developer/ldapcsharp/cnet/data/bovtuda.html

  • attrs:字符串数组,可以指定返回的属性的列表,不指定返回所有的属性

例如根据登录名来查询用户的示例代码如下:

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)
{//设置默认密码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;
}

注意点:

  • 默认密码的设置需要给密码加上引号

  • 默认情况下创建的用户是禁用的,如果要启用需要加上代码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;
}

移动用户到新的 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;
}

注意点:

  • 一个用户一旦创建,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 的版本有关),所以才有了本示例。本示例也会添加更多的使用场景,不断完善。

希望本文对您有所帮助。

dotNET Core 中怎样操作AD(续1)相关推荐

  1. dotNET Core 中怎样操作 AD?

    做企业应用开发难免会跟 AD 打交道,在之前的 dotNET FrameWork 时代,通常使用 System.DirectoryServices 的相关类来操作 AD ,在 dotNET Core ...

  2. 依赖注入在 dotnet core 中实现与使用:1 基本概念

    关于 Microsoft Extension: DependencyInjection 的介绍已经很多,但是多数偏重于实现原理和一些特定的实现场景.作为 dotnet core 的核心基石,这里准备全 ...

  3. 依赖注入在 dotnet core 中实现与使用:2 使用 Extensions DependencyInjection

    既然是依赖注入容器,必然会涉及到服务的注册,获取服务实例,管理作用域,服务注入这四个方面. 服务注册涉及如何将我们的定义的服务注册到容器中.这通常是实际开发中使用容器的第一步,而容器本身通常是由框架来 ...

  4. dotNET Core:编码规范

    在项目开发过程中,由于时间紧.任务重,很容易导致面向功能编程.实现相同的功能,代码可以写的很优雅,也可以写的很晦涩和复杂.现在的工作,都需要进行团队协作,代码就需要有一定的规范进行指引,因为我们需要写 ...

  5. dotNet Core 3.1 使用 Aspose (部署 Docker)

    在之前的文章<dotNET Core中使用Aspose(部署Docker)>中介绍了在 dotNet Core2.1 中使用 Aspose ,并部署到 Docker 中,现在 dotNET ...

  6. dotNET Core 3.X 使用 Autofac 来增强依赖注入

    在上一篇<dotNET Core 3.X 依赖注入>中简单介绍了 dotNET Core 框架本身的依赖注入功能,大部分情况下使用框架的依赖注入功能就可以满足了,在一些特殊场景下,我们就需 ...

  7. dotNET Core 3.X 依赖注入

    如果说在之前的 dotNET 版本中,依赖注入还是个比较新鲜的东西,那么在 dotNET Core 中已经是随处可见了,可以说整个 dotNET Core 的框架是构建在依赖注入框架之上.本文说说对 ...

  8. dotNET Core 3.X 请求处理管道和中间件的理解

    理解 dotNET Core 中的管道模型,对我们学习 dotNET Core 有很大的好处,能让我们知其然,也知其所以然,这样在使用第三方组件或者自己写一些扩展时,可以避免入坑,或者说避免同样的问题 ...

  9. 使用Novell.Directory.Ldap.NETStandard在.NET Core中验证AD域账号

    Novell.Directory.Ldap.NETStandard是一个在.NET Core中,既支持Windows平台,又支持Linux平台,进行Windows AD域操作的Nuget包. 首先我们 ...

最新文章

  1. zabbix 客户端安装
  2. 3D 投影矩阵学习1
  3. UNITY2018 真机开启deepprofiling的操作
  4. 奖金16万!首届电子商务AI算法大赛ECAA报名开启
  5. 击败李世石后,人工智能转战医疗:用大数据诊断眼科疾病
  6. Unable to locate package php5-curl
  7. 不重复的随机数JAVA、C#·适合初级人员玩耍。
  8. JDBC最基本CRUD操作工具类
  9. numpy求逆矩阵_线性代数精华2——逆矩阵的推导过程
  10. java hdu2014青年歌手大奖赛_评委会打分
  11. windows docker 设置镜像源_Windows10下搭建第一个Docker应用(Demo)
  12. STC1_FULLSCREEN_TABLE_CONTROL
  13. android内部培训视频_第三节(3)_常用控件(ViewPager、日期时间相关、ListView)
  14. 艰难时局下电子发现蓬勃发展
  15. 40个Qt学习小案例
  16. Beyond Compare的文档比较工具的设置
  17. Swift游戏实战-跑酷熊猫 03 熊猫跑动动画
  18. gst-launch-1.0
  19. 大众车机天宝187A Hack笔记
  20. Google Play上架总结(一)为什么要上架Google Play

热门文章

  1. Apache并发处理模块
  2. Mac OSX使用VMware Fusion安装windows虚拟机教程
  3. Mac OS使用技巧之一:查看Finder中的.bash_profile等系统隐藏文件
  4. 工程化,模块化,组件化,规范化
  5. 边写 Javascript 代码边玩游戏 – WarriorJS
  6. HealthKit有名无实,疑点重重
  7. 运营商在万物互联扮演什么角色?上海联通NB-IoT奠定基础
  8. 使用CDN引用jQuery
  9. Java里阻塞线程的三种实现方法
  10. nat+端口转发,使得宿主机secureCRT可以访问vbox里linux虚拟机