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

接上篇 Windows Server 2008 R2 配置AD(Active Directory)域控制器 对AD域结合常见需求用C#进行一些读取信息的操作^_^!

示例准备

  • 打开上一篇文章配置好的AD域控制器
  • 开始菜单-->管理工具-->Active Directory 用户和计算机
  • 新建组织单位和用户
  • 新建层次关系如下:

知识了解

  我们要用C#访问Active Directory非常容易,主要用到轻量目录访问协议 (LDAP) System.DirectoryServices命名空间下的两个组件类 DirectoryEntryDirectorySeacher

读取AD域信息示例

   示例在Framework 3.5下用Winform程序编写    主要结合常见需求读取组织单位(OU)及用户(User)信息,以及同步组织单位和用户的层次关系;      比较着重的还是用户的信息,特别是帐号、邮箱、SID等信息;

  • 下面我们开始连接域,并读取出示例准备中键好的组织单位和用户  

  首先编写代码用LDAP尝试对域进行访问   形式:LDAP://Domain

  #region## 是否连接到域
  /// <summary>
  /// 功能:是否连接到域
  /// 作者:Wilson
  /// 时间:2012-12-15
  /// http://msdn.microsoft.com/zh-cn/library/system.directoryservices.directoryentry.path(v=vs.90).aspx
  /// </summary>
  /// <param name="domainName">域名或IP</param>
  /// <param name="userName">用户名</param>
  /// <param name="userPwd">密码</param>
  /// <param name="entry">域</param>
  /// <returns></returns>
  private bool IsConnected(string domainName, string userName, string userPwd, out DirectoryEntry domain)
  {
      domain = new DirectoryEntry();
      try
      {
          domain.Path = string.Format("LDAP://{0}", domainName);
          domain.Username = userName;
          domain.Password = userPwd;
          domain.AuthenticationType = AuthenticationTypes.Secure;

          domain.RefreshCache();

          return true;
      }
      catch(Exception ex)
      {
          LogRecord.WriteLog("[IsConnected方法]错误信息:" + ex.Message);
          return false;
      }
  }
  #endregion

   传用参数,调IsConnected方法,结果如下

  • 连接上AD域后,接着我们找到根OU
  #region## 域中是否存在组织单位
  /// <summary>
  /// 功能:域中是否存在组织单位
  /// 作者:Wilson
  /// 时间:2012-12-15
  /// </summary>
  /// <param name="entry"></param>
  /// <param name="ou"></param>
  /// <returns></returns>
  private bool IsExistOU(DirectoryEntry entry, out DirectoryEntry ou)
  {
       ou = new DirectoryEntry();
       try
       {
           ou = entry.Children.Find("OU=" + txtRootOU.Text.Trim());

           return (ou != null);
       }
       catch(Exception ex)
       {
           LogRecord.WriteLog("[IsExistOU方法]错误信息:" + ex.Message);
           return false;
       }
   }
   #endregion

  传入以数,调用IsExistOU方法,结果如下

  • 下面来开始读取组织单位及用户的信息。

   示例为了看出层次关系及导出信息是类型区分,给OU和User新建了一个实体类和一个类型的枚举

 #region## 类型
    /// <summary>
    /// 类型
    /// </summary>
    public enum TypeEnum : int
    {
        /// <summary>
        /// 组织单位
        /// </summary>
        OU = 1,

        /// <summary>
        /// 用户
        /// </summary>
        USER = 2
    }
    #endregion

    #region## Ad域信息实体
    /// <summary>
    /// Ad域信息实体
    /// </summary>
    public class AdModel
    {
        public AdModel(string id, string name, int typeId, string parentId)
        {
            Id = id;
            Name = name;
            TypeId = typeId;
            ParentId = parentId;
        }

        public string Id { get; set; }

        public string Name { get; set; }

        public int TypeId { get; set; }

        public string ParentId { get; set; }
    }
    #endregion

     下面读取信息

private List<AdModel> list = new List<AdModel>();

     #region## 同步
        /// <summary>
        /// 功能:同步
        /// 创建人:Wilson
        /// 创建时间:2012-12-15
        /// </summary>
        /// <param name="entryOU"></param>
        public void SyncAll(DirectoryEntry entryOU)
        {           
            DirectorySearcher mySearcher = new DirectorySearcher(entryOU, "(objectclass=organizationalUnit)"); //查询组织单位                 

            DirectoryEntry root = mySearcher.SearchRoot;   //查找根OU

            SyncRootOU(root);

            StringBuilder sb = new StringBuilder();

            sb.Append("\r\nID\t帐号\t类型\t父ID\r\n");

            foreach (var item in list)
            {
                sb.AppendFormat("{0}\t{1}\t{2}\t{3}\r\n", item.Id, item.Name, item.TypeId, item.ParentId);
            }

            LogRecord.WriteLog(sb.ToString());

            MessageBox.Show("同步成功", this.Text, MessageBoxButtons.OK, MessageBoxIcon.Information);

            Application.Exit();
        }
        #endregion

        #region## 同步根组织单位
        /// <summary>
        /// 功能: 同步根组织单位
        /// 创建人:Wilson
        /// 创建时间:2012-12-15
        /// </summary>
        /// <param name="entry"></param>
        private void SyncRootOU(DirectoryEntry entry)
        {
            if (entry.Properties.Contains("ou") && entry.Properties.Contains("objectGUID"))
            {
                string rootOuName = entry.Properties["ou"][0].ToString();

                byte[] bGUID = entry.Properties["objectGUID"][0] as byte[];

                string id = BitConverter.ToString(bGUID);

                list.Add(new AdModel(id, rootOuName, (int)TypeEnum.OU, "0"));

                SyncSubOU(entry, id);
            }
        }
        #endregion

        #region## 同步下属组织单位及下属用户
        /// <summary>
        /// 功能: 同步下属组织单位及下属用户
        /// 创建人:Wilson
        /// 创建时间:2012-12-15
        /// </summary>
        /// <param name="entry"></param>
        /// <param name="parentId"></param>
        private void SyncSubOU(DirectoryEntry entry, string parentId)
        {
            foreach (DirectoryEntry subEntry in entry.Children)
            {
                string entrySchemaClsName = subEntry.SchemaClassName;

                string[] arr = subEntry.Name.Split('=');
                string categoryStr = arr[0];
                string nameStr = arr[1];
                string id = string.Empty;

                if (subEntry.Properties.Contains("objectGUID"))   //SID
                {
                    byte[] bGUID = subEntry.Properties["objectGUID"][0] as byte[];

                    id = BitConverter.ToString(bGUID);
                }

                bool isExist = list.Exists(d => d.Id == id);

                switch (entrySchemaClsName)
                {
                    case "organizationalUnit":

                        if (!isExist)
                        {
                            list.Add(new AdModel(id, nameStr, (int)TypeEnum.OU, parentId));
                        }

                        SyncSubOU(subEntry, id);
                        break;
                    case "user":
                        string accountName = string.Empty;

                        if (subEntry.Properties.Contains("samaccountName"))
                        {
                            accountName = subEntry.Properties["samaccountName"][0].ToString();
                        }

                        if (!isExist)
                        {
                            list.Add(new AdModel(id, accountName, (int)TypeEnum.USER, parentId));
                        }
                        break;
                }
            }
        }
        #endregion

  调用SyncAll方法循环输出list,结果如下,很清楚的可以看出层次关系

 //ID                                                 帐号             类型    父ID
        //58-D6-C4-32-6A-A1-99-48-A4-8B-C8-5D-BC-C9-3E-17    acompany        1       0
        //FB-44-91-AE-AC-73-2B-4D-9F-01-B1-E2-16-D3-CB-1B    department01    1       58-D6-C4-32-6A-A1-99-48-A4-8B-C8-5D-BC-C9-3E-17
        //47-9D-5B-91-60-22-D1-46-B0-CD-C7-B2-C7-D3-00-31    department03    1       FB-44-91-AE-AC-73-2B-4D-9F-01-B1-E2-16-D3-CB-1B
        //E3-AD-47-45-38-64-02-4D-B9-83-2C-50-67-50-4F-92    zw              2       47-9D-5B-91-60-22-D1-46-B0-CD-C7-B2-C7-D3-00-31
        //8A-D4-23-18-F3-6F-E1-47-93-7A-CC-07-76-4B-E7-86    zhongw          2       FB-44-91-AE-AC-73-2B-4D-9F-01-B1-E2-16-D3-CB-1B
        //BC-D0-34-85-67-2F-05-4D-B5-77-E3-F4-AD-51-45-02    department02    1       58-D6-C4-32-6A-A1-99-48-A4-8B-C8-5D-BC-C9-3E-17
        //1C-13-FA-66-E4-51-65-49-8B-DC-22-60-32-34-8F-22    wilson          2       BC-D0-34-85-67-2F-05-4D-B5-77-E3-F4-AD-51-45-02
        //84-E8-E5-9A-6B-56-E2-45-9A-87-54-D1-78-6B-D3-56    porschev        2       58-D6-C4-32-6A-A1-99-48-A4-8B-C8-5D-BC-C9-3E-17

DirectorySearcher.Filter属性扩充说明

     DirectorySearcher mySearcher = new DirectorySearcher(entryOU, "(objectclass=organizationalUnit)"); //查询组织单位     第二个参数是一个filter,也可以根据需求输入其它筛选条件,下面列出几个常用的

  更多高级筛选请查看:http://msdn.microsoft.com/zh-cn/library/system.directoryservices.directorysearcher.filter(v=vs.80).aspx

用户属性扩充说明(含图文属性对照)

   示例中只对用户进行了读取了几个属性,用过AD域的应该都知道,用户的属性较多也比较常用。   下面通过AD域的用户详细信来对照一下相应的属性名

  • 常项选项卡
  • 地址选项卡
  • 帐户选项卡
  • 电话选项卡
  • 组织选项卡

示例下载

 示例下载  示例代码,写得比较简陋,有需要就下载了将就着看一下吧^_^!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏技术小讲堂

ASP.NET AJAX(15)__构建高性能ASP.NET AJAX应用UpdatePanel的性能问题使用UpdatePanel的注意事项脚本加载避免脚本阻塞页面显示AjaxControlTool

UpdatePanel的性能问题 在UpdatePanle使用的时候,它每次的更新都是将整个页面回送的,而且也会加上一些他更新的标记,所以往往它传递的数据量比传...

334100
来自专栏Jackson0714

玩转PowerShell第一节——【后台任务处理】-技术&分享

32760
来自专栏领域驱动设计DDD实战进阶

微服务实战(七):落地微服务架构到直销系统(实现命令与命令处理器)

我们先来看看CQRS架构,你对下图的架构还有印象吗?每个组件的功能都还清楚吗?如果有疑问,请查考文章《微服务实战(五):落地微服务架构到直销系统(构建高性能大并...

21730
来自专栏LanceToBigData

HttpClient(二)HttpClient使用Ip代理与处理连接超时

前言   其实前面写的那一点点东西都是轻轻点水,其实HttpClient还有很多强大的功能:   (1)实现了所有 HTTP 的方法(GET,POST,PUT,...

47780
来自专栏林德熙的博客

win10 uwp smms图床 进行HttpClient post参数错误win10 uwp post 上传文件所有代码

本文,如何使用smms图床上传图片,用到win10 uwp post文件,因为我是渣渣,如果本文有错的,请和我说,在本文评论,或发给我邮箱,请不要发不良言论

16520
来自专栏蘑菇先生的技术笔记

Net作业调度(五)—quartz.net动态添加job设计

32760
来自专栏王清培的专栏

Redis 数据结构与内存管理策略(下)

Redis 数据结构与内存管理策略(下) 标签: Redis Redis数据结构 Redis内存管理策略 Redis数据类型 Redis类型映射 作者:王清培...

34680
来自专栏GuZhenYin

ASP.NET Core文件上传与下载(多种上传方式)

前言 前段时间项目上线,实在太忙,最近终于开始可以研究研究ASP.NET Core了. 打算写个系列,但是还没想好目录,今天先来一篇,后面在整理吧. ASP.N...

66760
来自专栏Porschev[钟慰]的专栏

【2013年】开发常见问题回顾(一)

记录开发中遇到的和别人问的较多的问题.... IE10中LinkButton不可用     这应该是2013年初遇到的一个BUG,当使用Asp.Net开发Web...

30050
来自专栏丑胖侠

Zookeeper客户端API之创建会话(六)

Zookeeper对外提供了一套Java的客户端API。本篇博客主要讲一下创建会话。 创建项目 首选,创建一个基于maven管理的简单java工程。在pom文件...

21590

扫码关注云+社区

领取腾讯云代金券