前言

本章聊Active Directory的组织单位(OU)的新增、修改、移动等操作,使用.NET Framework 为我们提供的System.DirectoryServices程序集。

不积跬步无以至千里。Active Directory开发系列将在本章开始侧重于代码(有部分人肯定很高兴了,可以COPY嘛),因为个人认为必要的理论知识和基础代码在前面已经记录了很多,这章开始若有不理解的地方请回看以前的文章。

封装基础ADHelper

这段ADHelper 是为了后面组织单位的新增,修改,移动而准备的代码段,在实际项目开发中当然是不够看的,不过讲本章涉及内容已经足够了。

  1. public class ADHelper
  2. {
  3. #region 构造单例
  4. private ADHelper() { }
  5. public static readonly ADHelper Instance = new ADHelper();
  6. #endregion
  7. #region 公共属性
  8. private static string DomainServiceIP = "192.168.241.3";
  9. private static string UserName = @"Domain";
  10. private static string Password = "p@ssw0rd";
  11. private DirectoryEntry rootEntry = null;
  12. #endregion
  13. #region 公共方法
  14. /// <summary>
  15. /// 域节点DirectoryEntry对象
  16. /// </summary>
  17. public DirectoryEntry DomainRootEntry
  18. {
  19. get
  20. {
  21. if (rootEntry == null)
  22. {
  23. try
  24. {
  25. rootEntry = new DirectoryEntry("LDAP://" + DomainServiceIP, UserName, Password);
  26. }
  27. catch (Exception ex)
  28. {
  29.  
  30. throw ex;
  31. }
  32. }
  33. return rootEntry;
  34. }
  35. }
  36. /// <summary>
  37. /// AD查询器公共方法封装
  38. /// </summary>
  39. /// <typeparam name="T">DirectorySearcher或SearchResultCollection</typeparam>
  40. /// <param name="SearchRoot">查询器的查询起点</param>
  41. /// <param name="Filter">查询过滤器</param>
  42. /// <param name="SearchScope">查询方式</param>
  43. /// <returns></returns>
  44. public T GetSearchResultOrSearchCollection<T>(DirectoryEntry SearchRoot, string Filter, SearchScope SearchScope) where T : class
  45. {
  46. DirectorySearcher Searcher = new DirectorySearcher();
  47. if (SearchRoot == null)
  48. SearchRoot = DomainRootEntry;
  49. using (SearchRoot)
  50. {
  51. try
  52. {
  53. Searcher.Filter = Filter;
  54. Searcher.SearchRoot = SearchRoot;
  55. Searcher.SearchScope = SearchScope;
  56. if (typeof(T).Name == "SearchResult")
  57. return Searcher.FindOne() as T;
  58. else
  59. return Searcher.FindAll() as T;
  60. }
  61. catch (Exception ex)
  62. {
  63.  
  64. throw ex;
  65. }
  66. }
  67. }
  68. /// <summary>
  69. /// 获取DirectoryEntry对象
  70. /// </summary>
  71. /// <param name="proterEntry">查询起点</param>
  72. /// <param name="filter">查询条件</param>
  73. /// <returns></returns>
  74. public DirectoryEntry GetEntry(DirectoryEntry proterEntry, string filter)
  75. {
  76. SearchResult SearchResult = GetSearchResultOrSearchCollection<SearchResult>(proterEntry, filter, SearchScope.Subtree);
  77. if (SearchResult != null)
  78. return SearchResult.GetDirectoryEntry();
  79. else
  80. return DomainRootEntry;
  81. }
  82. #endregion
  83. }

这段ADHelper代码顾名思义其实和SQLHelper一样,是对AD操作的最基础层的一段代码,如果前面的文章有仔细了解过,那么这段代码我相信应该不成问题,只不过是做了封装而已,我们将主要精力放在后面实际的操作OU上吧。

我们还要再封装一个组织单位的实体类方便我们使用。

  1. public class ADOrgUnit
  2. {
  3. #region 属性
  4. /// <summary>
  5. /// GUID
  6. /// </summary>
  7. public string ObjectGuid { get; set; }
  8. /// <summary>
  9. /// 标示名
  10. /// </summary>
  11. public string DistinguishedName { get; set; }
  12. /// <summary>
  13. /// OU
  14. /// </summary>
  15. public string Ou { get; set; }
  16. /// <summary>
  17. /// 描述
  18. /// </summary>
  19. public string Description { get; set; }
  20. #endregion
  21. }

我的测试域控服务器如下:

如果之前的文章有做过了解,看到图片上的数据排列,我们完全可以推算出某AD对象的DN。

新增组织单位(OU)

我们目标是在域节点创建新的OU,如果之前的文章有理解,那么我们可以直接判断出DomainDNS的DN为:DC=IFire47,DC=com

  1. static void Main(string[] args)
  2. {
  3. ADOrgUnit adOrgUnit = new ADOrgUnit();
  4. //新增OU的名称
  5. adOrgUnit.Ou = "IFire47";
  6. //新增OU的描述
  7. adOrgUnit.Description = "IFire47测试组织单位";
  8. try
  9. {
  10. //我们在域节点创建新的组织单位,所以根据封装的ADHelper调用此方法。
  11. using (DirectoryEntry parentEntry = ADHelper.Instance.DomainRootEntry)
  12. {
  13. //创建新OU,并接受新OU的DiectoryEntry对象
  14. DirectoryEntry ouEntry = parentEntry.Children.Add("ou=" + adOrgUnit.Ou, "organizationalUnit");
  15. //为创建的新OU赋值属性
  16. if (!String.IsNullOrEmpty(adOrgUnit.Description))
  17. ouEntry.Properties["description"].Value = adOrgUnit.Description;
  18. //保存
  19. ouEntry.CommitChanges();
  20. }
  21. }
  22. catch (Exception ex)
  23. {
  24. throw ex;
  25. }
  26. }

因为我们是在域节点创建的新OU我们看下新OU的DN属性

这跟之前文章讲解不谋而合,所以在这里我们将从实际代码测试中对LDAP和DN的概念有更进一步的认识与理解。对于这块代码的理解,这是我根据.NET的提示及个人理解做的整理:

  1. // 摘要:获取 Active Directory 域服务层次结构中此节点的子项。
  2. // 返回结果:一个 System.DirectoryServices.DirectoryEntries 对象,其中包含 Active Directory 域服务层次结构中此节点的子项。
  3. [Browsable(false)]
  4. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  5. [DSDescription("DSChildren")]
  6. public DirectoryEntries Children { get; }
  7. // 摘要: 在容器中创建一个新项。
  8. // name:新项名称。
  9. // schemaClassName:用于此新项的架构名称。即新创建的对象类别,详细查看上章
  10. // 返回结果:新项的 System.DirectoryServices.DirectoryEntry 对象。
  11. public DirectoryEntry Add(string name, string schemaClassName);
  12. // 摘要:获取此 System.DirectoryServices.DirectoryEntry 对象的 Active Directory 域服务属性。
  13. // 返回结果:一个 System.DirectoryServices.PropertyCollection 对象,包含此项所设属性。
  14. [Browsable(false)]
  15. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  16. [DSDescription("DSProperties")]
  17. public PropertyCollection Properties { get; }
  18. //摘要: 将目录项所作更改保存到基础目录存储中。
  19. public void CommitChanges();

修改组织单位(OU)

我们修改刚才新添加的OU的名称及描述属性

  1.     static void Main(string[] args)
  2. {
  3. ADOrgUnit adOrgUnit = new ADOrgUnit();
  4. //修改OU的新名称
  5. adOrgUnit.Ou = "IceFire47";
  6. //修改OU的新描述
  7. adOrgUnit.Description = "IceFire47测试组织单位";
  8. //所要修改的OU的DN属性
  9. adOrgUnit.DistinguishedName = "OU=IceFire47,DC=IFire47,DC=com";
  10. try
  11. {
  12. DirectoryEntry ouEntry = GetEntryByOrgDN(adOrgUnit.DistinguishedName);
  13. if (!string.IsNullOrEmpty(adOrgUnit.Ou))
  14. {
  15. ouEntry.Rename("ou=" + adOrgUnit.Ou);
  16. ouEntry.CommitChanges();
  17. }
  18. //修改描述属性,属性是数组类型的,要做一系列容错判断
  19. if (ouEntry.Properties.Contains("description"))//判断是否存在这个属性
  20. {
  21. if (adOrgUnit.Description != null && !string.IsNullOrEmpty(adOrgUnit.Description))//描述是否为空
  22. ouEntry.Properties["description"][] = adOrgUnit.Description;//不空修改属性
  23. else//
  24. ouEntry.Properties["description"].RemoveAt();//为空移除描述属性
  25. }
  26. else
  27. {
  28. if (adOrgUnit.Description != null && !string.IsNullOrEmpty(adOrgUnit.Description))//不为空添加属性
  29. ouEntry.Properties["description"].Add(adOrgUnit.Description);
  30. }
  31. //保存
  32. ouEntry.CommitChanges();
  33. }
  34. catch (Exception ex)
  35. {
  36. throw ex;
  37. }
  38. }
  39. /// <summary>
  40. /// 根据OU的DN属性值查询OU对象
  41. /// </summary>
  42. /// <param name="distinguishedName">DN属性值</param>
  43. /// <returns></returns>
  44. public static DirectoryEntry GetEntryByOrgDN(string distinguishedName)
  45. {
  46. string filter = "(&(objectClass=organizationalUnit)(distinguishedName=" + distinguishedName + "))";
  47. return ADHelper.Instance.GetEntry(null, filter);
  48. }

这的逻辑根据自身的业务场景可以做调整,并不一定要根据DN去查询然后修改,也可以根据name等属性查询,只不过要修改Filter并修改传值。而且我们修改了这个OU对象后,它的DN也将自动修改,因为我们定义了新的OU名称。

这里的赋值做了一系列的判断,是因为AD对象的属性并不一定是String还有可能是String[],从属性编辑器中看下描述属性如下,所以直接赋值保存做判断后赋值修改时直接追加根据自身业务场景而定。

移动组织单位(OU)

我们将刚才修改的OU移动北京分公司的OU当中

  1.    static void Main(string[] args)
  2. {
  3. //需要移动的OU的DN
  4. string OrgUnitDN = "OU=IceFire47,DC=IFire47,DC=com";
  5. //要移动到的容器的DN,这里不一定是OU也可以是域节点
  6. string targetOrgDN = "OU=北京分公司,DC=IFire47,DC=com";
  7. using (DirectoryEntry ouEntry = GetEntryByOrgDN(OrgUnitDN))
  8. {
  9. using (DirectoryEntry targetOU = GetEntryByOrgDN(targetOrgDN))
  10. {
  11. try
  12. {
  13. ouEntry.MoveTo(targetOU);
  14. ouEntry.CommitChanges();
  15. }
  16. catch (Exception ex)
  17. {
  18. throw ex;
  19. }
  20. }
  21. }
  22. }
  23. /// <summary>
  24. /// 根据OU的DN查询OU对象
  25. /// </summary>
  26. /// <param name="distinguishedName">DN属性</param>
  27. /// <returns></returns>
  28. public static DirectoryEntry GetEntryByOrgDN(string distinguishedName)
  29. {
  30. string filter = "(&(objectClass=organizationalUnit)(distinguishedName=" + distinguishedName + "))";
  31. return ADHelper.Instance.GetEntry(null, filter);
  32. }

在移动OU时,新OU的DN也将自动改变。同理,这里的一部分逻辑也并不是固定的,我们也可以根据自身业务场景做调整,关键还是在获取DirectoryEntry对象根据项目需求而定。而且OU的移动智能在域节点或者另一个OU中,不能将组织单位移动到某个组或者用户或者计算机中,而且需要注意的是,当OU移动时,移动的OU内的所有对象将一起被移动。

结语

本章主要是讲解AD中组织单位的一系列操作,删除操作调用DirectoryEntry.DeleteTree();DirectoryEntry.CommitChanges();即可,但是实际项目中删除操作要慎重,删除OU此容器内的所有对象将一并删除。

这里的所有示例都没有做容错处理,比如说新建OU时要判断当前节点下是否存在同名的OU存在若存在则不能创建等等,因为从之前的文章中已经讲解过DN在全局是唯一的,这就意味着在同一节点中不可能存在同名的OU,在不同OU中可以存在同名OU,因为就算同名但是他们的DN是不一样的。

在本章对属性赋值的判断,有些属性做判断而有些属性不需要可以直接赋值,这些都取决于Windowsd对具体AD对象的定义,我将会抽空在上一篇的常用属性的注释中做标注。而OU对象转换成.NET中的实体对象则在User具体操作章节一起讲解,因为都是操作DirectoryEntry对象,本质上都是一样。只不过可能加载的DirectoryEntry属性集会根据OU或User等有一些区别,但是整体的转换过程都是一样的。以上是本章全部内容,明天还要上班睡觉。

本章最后更新时间:2017年4月24日00:25:45


作者:IFire47 出处:http://www.cnblogs.com/IFire47/

 
本文版权作者博客园共有,欢迎转载。未经作者同意下,必须在文章页面明显标出原文链接及作者,否则保留追究法律责任的权利。
 
个人原创,若有错误或补充请联系修改。本文会根据作者的一步步成长做一定程度的更新和补充。

Active Directory组织单位(Organizational Unit)操作汇总的更多相关文章

  1. Active Directory的基本概念

    前言 本文是面对准备加入Active Directory编程的初学者的一份文章,主要是讲解Active Directory(活动目录)的一些概念和相关知识.这篇文章本来是不想写下来的,因为概念性内容的 ...

  2. Active Directory的DirectoryEntry与DirectorySearcher初识及Filter语法

    前言 增删改查,我想查询是最先要说的一个了.本章主要记录使用.NET Framework进行对域控服务器对象的查询操作,介绍DirectoryEntry与DirectorySearcher(搜索器)及 ...

  3. DNS笔记 DNS区域集成到 Active Directory

    可以将 DNS 区域集成到 Active Directory 中以提供增强的容错功能和安全性.OpenDNS   Google Public DNS往返时间 (RTT) 远程访问服务 (RAS)域名与 ...

  4. C# AD(Active Directory)域信息同步,组织单位、用户等信息查询

    示例准备 打开上一篇文章配置好的AD域控制器 开始菜单-->管理工具-->Active Directory 用户和计算机 新建组织单位和用户   新建层次关系如下: 知识了解 我们要用C# ...

  5. C#操作Active Directory(AD)详解

    1. LDAP简介 LDAP(轻量级目录访问协议,Lightweight Directory Access Protocol)是实现提供被称为目录服务的信息服务.目录服务是一种特殊的数据库系统,其专门 ...

  6. Windows Server 2016-OU组织单位日常操作

    技术无所谓贵贱,既然曾经做过就总该是要留下点什么,毕竟做技术这些年给我们留下太多太多的成长经历,总有人问这些已经很皮毛了为什么还要写,其实没那么多花哨理由,就是想着做或者不做这一块总是要对过往做个简单 ...

  7. 操作Active Directory C#

    .Net平台操作活动目录Active Directory,使用System.DirectoryServices.ActiveDirectory,主要是User OU 和Group的操作. 代码运行了一 ...

  8. PHP 通过LDAP协议,操作Windows Active Directory

    原文地址:http://hi.baidu.com/lllangxx/item/3ccb7cdfa13b56eb3dc2cb39 一.学习如何管理Active Directory Active Dire ...

  9. Active Directory的LDAP协议与DN(Distinguished Name)详解

    前言 光copy几段代码的文章没什么意思,本章上最基础的代码,主要是为了从编程方面聊LDAP和DN,其它的后面聊,一步步慢慢来吧. Active Directory编程须知 1.域控服务器: Wind ...

随机推荐

  1. 在 Ubuntu 16.04 上安装 Eclipse Oxygen

    2017 年 6 月 28 日,Eclipse 社区(the Eclipse Community)发布了 Eclipse Oxygen.本文记录了我在 Ubuntu 16.04 上安装 Eclipse ...

  2. Python ping 模块

    使用socket模块也可以获得域名对应的ip,参考:https://blog.csdn.net/c465869935/article/details/50850598 print socket.get ...

  3. djang中的request.user对象中的方法

    print(dir(request.user)) ['__class__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__', ...

  4. 一次向linux开源社区提交补丁的经历

    背景 在开发过程中,偶然发现了spinand驱动的一个bug,满怀欣喜地往社区提补丁.这是怎么样的一个bug呢? static int spinand_mtd_read(struct mtd_info ...

  5. 【CF675E】Trains and Statistic(贪心,DP,线段树优化)

    题意:a[i]表示从第i个车站可以一张票到第[i+1,a[i]]这些车站;p[i][j]表示从第i个车站到第j个车站的最少的票数,现在要求∑dp[i][j](1<=i<=n,i<j& ...

  6. 标准C程序设计七---76

    Linux应用             编程深入            语言编程 标准C程序设计七---经典C11程序设计    以下内容为阅读:    <标准C程序设计>(第7版) 作者 ...

  7. 标准C程序设计七---67

    Linux应用             编程深入            语言编程 标准C程序设计七---经典C11程序设计    以下内容为阅读:    <标准C程序设计>(第7版) 作者 ...

  8. PHP错误捕获处理

    PHP错误捕获处理 一般捕获错误使用的方法是: try{ ...}catch(Exception $e){ echo $e->getMessage();} 或者 set_exception_ha ...

  9. 服务器SSL/TLS快速检测工具TLLSSLed

    服务器SSL/TLS快速检测工具TLLSSLed   现在SSL和TLS被广泛应用服务器的数据加密中,如网站的HTTPS服务.所以,在渗透测试中如何快速检测服务器的SSL和TLS配置寻找安全漏洞,就显 ...

  10. Netty-----初探

    今天看gateway 实现的时候看到个哥们基于的netty实现的gateway.so,解析一下Netty. 废话少说,maven pom 引入,down 下jar包.看了下netty的包结构,还是挺明 ...