dotNET Core 中怎样操作 AD?
做企业应用开发难免会跟 AD 打交道,在之前的 dotNET FrameWork 时代,通常使用 System.DirectoryServices 的相关类来操作 AD ,在 dotNET Core 中没有这个命名空间,在张善友大佬的推荐下,知道了 Novell.Directory.Ldap。
操作 AD,通常有两种常见的场景:
将第三方数据源数据(人事系统)同步到 AD 中
将 AD 数据同步到自己的数据库中
本文将介绍在 dotNET Core 中使用 Novell.Directory.Ldap 将 AD 数据同步到数据库的操作。
环境
dotNET Core:2.1
Novell.Directory.Ldap.NETStandard2_0:3.1.0
安装 Novell.Directory.Ldap 包
在 VS2019 中添加 NuGet 包引用,如下图:
安装完成后,在类中添加using Novell.Directory.Ldap;
引用便可使用相关的 API 方法了。
同步思路
1、连接 AD
基本操作
同步方法
public bool Sync()
{ADConnect();if (_connection == null){throw new Exception("AD连接错误,请确认AD相关信息配置正确!");}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;}//设置其他属性的值_org.UpdateOrg(org);return org;}org = new Org{Id = orgId,ParentId = parentOrg.Id,};//设置其他属性的值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;//设置其他属性的值this._user.UpdateUser(user);return user;}user = new User{Id = userId,ParentId = parentOrg.Id};//设置其他属性的值this._user.AddUser(user);return user;
}
辅助方法
为了方便代码的编写和复用,将一些操作提取到了扩展方法中。
获取 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 的 子级
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 的修改时间
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);
}
根据名称获取 Entry 中的属性值
public static string AttrStringValue(this LdapEntry entry, string attrName)
{if (!entry.ContainsAttr(attrName)){return string.Empty;}return entry.getAttribute(attrName).StringValue;
}
总结
文中没有做更多文字性的介绍,可以从下面链接中下载代码进行调试就很容易理解了。
参考
示例代码:https://github.com/oec2003/StudySamples/tree/master/DotNetCoreAdDemo/DotNetCoreAdDemo
祝大家国庆假期快乐!
dotNET Core 中怎样操作 AD?相关推荐
- dotNET Core 中怎样操作AD(续1)
在之前的文章<dotNET Core 中怎样操作 AD?>中主要以AD的数据同步到数据库的场景来描述了在 dotNetCore 中怎样操作AD,本文将继续介绍一些在 dotNetCore ...
- 依赖注入在 dotnet core 中实现与使用:1 基本概念
关于 Microsoft Extension: DependencyInjection 的介绍已经很多,但是多数偏重于实现原理和一些特定的实现场景.作为 dotnet core 的核心基石,这里准备全 ...
- 依赖注入在 dotnet core 中实现与使用:2 使用 Extensions DependencyInjection
既然是依赖注入容器,必然会涉及到服务的注册,获取服务实例,管理作用域,服务注入这四个方面. 服务注册涉及如何将我们的定义的服务注册到容器中.这通常是实际开发中使用容器的第一步,而容器本身通常是由框架来 ...
- dotNET Core:编码规范
在项目开发过程中,由于时间紧.任务重,很容易导致面向功能编程.实现相同的功能,代码可以写的很优雅,也可以写的很晦涩和复杂.现在的工作,都需要进行团队协作,代码就需要有一定的规范进行指引,因为我们需要写 ...
- dotNet Core 3.1 使用 Aspose (部署 Docker)
在之前的文章<dotNET Core中使用Aspose(部署Docker)>中介绍了在 dotNet Core2.1 中使用 Aspose ,并部署到 Docker 中,现在 dotNET ...
- dotNET Core 3.X 使用 Autofac 来增强依赖注入
在上一篇<dotNET Core 3.X 依赖注入>中简单介绍了 dotNET Core 框架本身的依赖注入功能,大部分情况下使用框架的依赖注入功能就可以满足了,在一些特殊场景下,我们就需 ...
- dotNET Core 3.X 依赖注入
如果说在之前的 dotNET 版本中,依赖注入还是个比较新鲜的东西,那么在 dotNET Core 中已经是随处可见了,可以说整个 dotNET Core 的框架是构建在依赖注入框架之上.本文说说对 ...
- dotNET Core 3.X 请求处理管道和中间件的理解
理解 dotNET Core 中的管道模型,对我们学习 dotNET Core 有很大的好处,能让我们知其然,也知其所以然,这样在使用第三方组件或者自己写一些扩展时,可以避免入坑,或者说避免同样的问题 ...
- 使用Novell.Directory.Ldap.NETStandard在.NET Core中验证AD域账号
Novell.Directory.Ldap.NETStandard是一个在.NET Core中,既支持Windows平台,又支持Linux平台,进行Windows AD域操作的Nuget包. 首先我们 ...
最新文章
- AI洞观 | 一文读懂英特尔的AI之路
- 2020-12-09 深度学习 卷积核/过滤器、特征图(featue map)、卷积层
- liunx 加入域控_让Linux使用Windows域控制器做用户认证
- 牛客网暑期ACM多校训练营(第三场)H - Diff-prime Pairs
- 升级项目到.NET Core 2.0,在Linux上安装Docker,并成功部署
- P1020 导弹拦截(n*log n时间的最长上升子序列思想)
- Linux 设备驱动模型中的class(类)
- file 选择的图片作为背景图片_酷炫!用Python把桌面变成实时更新的地球图片
- RabbitMQ 最新版安装 (Linux环境)
- 跟随者数字解码_跟随模式的数字
- mysql 重复了更新_MYSql id相同就更新
- netcore之hello
- SQL Server里面如何检查没有释放的游标
- 蜂鸣器播放青鸟,含曲谱(小萌白新文)
- OpenKG祝大家端午安康
- 单片机(51) 什么是编码器?什么是译码器?
- 瑞吉外卖01-项目整体介绍
- 3D简单壳体CAD绘制
- 【学习OpenCV4】案例3:OpenCV Python语言开发环境搭建
- python人力成本数据测算_人力成本分析计算公式大全
热门文章
- linkButton与Button 的click事件与onclientClick事件
- excel if in函数_【Excel函数】Small+Index+IF 一对N返回
- python博客访问量_史诗级干货-python爬虫之增加CSDN访问量
- 绘制三维散点图_SPSS统计作图教程:三维散点图
- 学go语言能做什么工作?
- 补充一点地理知识(以洲来划分各个国家(240个))
- mongoDB的副本机制
- DCOS实践分享(6):基于DCOS的大数据应用分享
- Visual Entity 手册(十一)代码生成设置
- DBDesigner 4 与 MySql 5 不能连接主要是驱动的原因