Active Directory的DirectoryEntry与DirectorySearcher初识及Filter语法
前言
增删改查,我想查询是最先要说的一个了。本章主要记录使用.NET Framework进行对域控服务器对象的查询操作,介绍DirectoryEntry与DirectorySearcher(搜索器)及Filter(搜索过滤器)语法,并对AD对象常用属性做记录。
DirectoryEntry与DirectorySearcher
使用C#语言对域控服务器的AD对象进行查询操作,DirectoryEntry和DirectorySearcher是必须要了解的两个类。System.DirectoryServices 命名空间用以从托管代码简便地访问 Active Directory。该命名空间包含了两个组件类,即DirectoryEntry和DirectorySearcher,它们使用AD服务接口(ADSI)技术。
DirectoryEntry:我们知道Active Directory中的数据是树状的,并且是层次型存储。而DirectoryEntry类就是为了封装 Active Directory 层次结构中的节点或对象。使用此类绑定到对象、读取属性和更新特性。DirectoryEntry 与帮助器类一起为生存期管理和导航方法提供支持,包括创建、删除、重命名、移动子节点和枚举子级。
https://msdn.microsoft.com/zh-cn/library/system.directoryservices.directoryentry_members(v=vs.80).aspx
DirectorySearcher:顾名思义这个对象是主要执行针对Active Directory域服务的查询。
https://msdn.microsoft.com/zh-cn/library/system.directoryservices.directorysearcher(v=vs.110).aspx
目前我的域控服务器在域上AD对象结构如下:

一段示例代码,目的是查询用户李四
static void Main(string[] args)
{
//声明一个AD对象搜索器
DirectorySearcher searcher = new DirectorySearcher();
//设置此搜索器的搜索起点
searcher.SearchRoot = DomainRootEntry();
//设置此搜索器的搜索语句
searcher.Filter = "(&(objectClass=user)(name=李四))";
//设置此搜索器的查询范围
searcher.SearchScope = SearchScope.Subtree;
//执行查询,有FindOne与FindAll之别
SearchResult result = searcher.FindOne();
if (result != null)
{
//转换为李四对象
DirectoryEntry userEntry = result.GetDirectoryEntry();
}
}
/// <summary>
/// 域控服务器IP
/// </summary>
private static string DomainServiceIP = "192.168.241.3";
/// <summary>
/// 域控服务器用户名
/// </summary>
private static string UserName = @"Domain";
/// <summary>
/// 域控服务器密码
/// </summary>
private static string Password = "p@ssw0rd"; /// <summary>
/// 获取域控服务器中域节点对象
/// </summary>
public static DirectoryEntry DomainRootEntry()
{
DirectoryEntry rootEntry = null;
try
{
rootEntry = new DirectoryEntry("LDAP://" + DomainServiceIP, UserName, Password);
return rootEntry;
}
catch (Exception ex)
{
throw ex;
}
}

这里的DirectoryEntry对象封装 Active Directory 域层次结构中的节点对象。通过DirectorySearcher搜索器来查询用户李四。如代码所示DirectorySearcher对象使用有几个地方要了解。
SearchRoot:获取或设置一个值(DirectoryEntry对象,一般为DC或者OU),该值指示 Active Directory 域服务层次结构中的节点,从该节点处开始搜索。说白了就是说我这个查询器查询从这个节点开始向下查询包括这个节点。
SearchScope:获取或设置指示服务器遵循的搜索范围的值。为SearchScope的enmu类型。
//指定使用 System.DirectoryServices.DirectorySearcher 对象执行的目录搜索的可能范围。
public enum SearchScope
{
// 将搜索限于基对象。结果最多包含一个对象。当 System.DirectoryServices.DirectorySearcher.AttributeScopeQuery
// 属性指定用于某一搜索时,搜索范围必须设置为 System.DirectoryServices.SearchScope.Base。
Base = ,
// 搜索基对象的直接子对象,但不搜索基对象。
OneLevel = ,
// 搜索整个子树,包括基对象及其所有子对象。如果未指定目录搜索的范围,则执行 System.DirectoryServices.SearchScope.Subtree
// 类型的搜索。
Subtree =
}
FindOne();与FindAll();的区别:FindOne执行搜索返回搜索过程中找到的第一项,返回结果为一个System.DirectoryServices.SearchResult对象。而FindAll执行搜索并返回找到的项的集合,返回结果是System.DirectoryServices.SearchResultCollection对象。
剩下的就是这个Filter比较复杂了,我们继续往下看。
Filter语法详解及属性扩充
Filter:(官方解读为:搜索过滤器)它为DirectorySearcher(搜索器)定义一个搜索条件,为的是使我们的搜索器更有效的搜索。有点像ADO中的T-SQL语句。Filter属性值以 LDAP 格式表示的筛选条件,用Unicode字符串表示。下表列出了一些例子。
| Search filter(搜索过滤器) | Description(描述) |
| "(objectClass=*)" | 所有的对象。 |
| "(&(objectCategory=person)(objectClass=user)(!cn=andy))" | 所有的用户对象,但“andy”除外 |
| "(sn=sm*)" | 所有对象的满足姓氏从“SM”开头。 |
| "(&(objectClass=user)(name=李四))" | 所有名称为李四的用户对象 |
Filter语法详解:
表达式:属性名=Value
通配符:“*”,该字符出现在表达式Value中,匹配该字符位置后的内容,类似于SQL中的“%”;例子如下:
|
Description(描述) | |
| ”(objectClass=*)“ | 得到所有对象 | |
| “(cn=*bob*)” | 得到的对象,名称含有“bob”: | |
| ”(&(objectClass=user)(email=*))“ | 得到包含电子邮件属性的所有用户: |
逻辑运算符:
| Logical operator(逻辑运算符) | Description(描述) |
| = | 等于 |
| & | 和 |
| | | 或 |
| ! | 非 |
| ~= | 约等于 |
| <= | 字典序小于或者等于 |
| >= | 字典序大于或者等于 |
语法类型:(Key=Value)为一个表达式,两个表达式满足某些条件(|或、&且、!非)则放在两个表达前面并用括号括起来。如:(&(objectClass=user)(mobile=132*)) ,电话为132开头的所有用户。(&(表达式1=value)(表达式2=value)),该filter结果为取表达式1和表达式2同时匹配的内容。
特殊字符:如果以下任何特殊字符必须出现在搜索过滤的文字中,他们必须通过的转义替换。
| ASCII字符 | 转义替代 |
| * | \2a |
| ( | \28 |
| ) | \29 |
| \ | \5c |
| NULL | \00 |
| / | \2f |
DirectorySearcher.Filter类型属性扩充说明(不区分大小写):
| 筛选条件 | 值 |
| 域 | (objectClass=domainDNS) |
| 组织单位 | (objectClass=organizationalUnit) |
| 用户 | (&(objectCategory=person)(objectClass=user))或者(&(objectClass=User)(!objectClass=computer)) |
| 计算机 | (objectCategory=computer) |
| 组 | (objectCategory=group) |
| 联系人 | (objectCategory=contact) |
| 共享文件夹 | (objectCategory=volume) |
| 打印机 | (objectCategory=printQueue) |
以上是一些常用类型检索条件,值得注意的是(objectClass=user)并不只是检索用户还包括计算机。所以要要做处理。当然检索的条件不知以上这些。AD中对象的属性都可以做检索条件,我们最后看看AD中的对象属性有哪些是我们常用的。
Active Directory常用属性
用户(User)常用选项卡中的属性

| 选项卡项名 | 属性名 | 备注 |
| 名称 | name | 在同一节点下唯一,string |
| 姓(L) | sn | string |
| 名(F) | givenName | string |
| 英文缩写(I) | initials | string |
| 显示名称(S) | displayName | 域内不唯一,但是在同一个组织单位内唯一 |
| 描述(D) | description | string[] |
| 办公室(C) | physicalDeliveryOfficeName | string |
| 电话号码(T) | telephoneNumber | string |
| 电子邮件(M) | string | |
| 网页(W) | wWWHomePage | string |

| 选项卡项名 | 属性名 | 备注 |
| 用户登录名(U) | userPrincipalName | 全域内唯一,string |
| 用户登录名(Windows 2000 以前版本)(W) | sAMAccountName | 全域内唯一,string |

| 选项卡项名 | 属性名 | 备注 |
| 国家/地区(O) | co | string |
| 省/自治区(V) | st | string |
| 市/县(C) | l | string |
| 街道(S) | streetAddress | string |
| 邮政信箱(B) | postOfficeBox | string[] |
| 邮政编码(Z) | postalCode | string |

| 选项卡项名 | 属性名 | 备注 |
| 家庭电话(M) | homePhone | string |
| 寻呼机(P) | pager | string |
| 移动电话(B) | mobile | string |
| 传真(F) | facsimileTelephoneNumber | string |
| IP电话(I) | ipPhone | string |
| 注释 | info | string |

| 选项卡项名 | 属性名 | 备注 |
| 公司(C) | company | string |
| 部门(D) | department | string |
| 职务(J) | title | string |
| 经理-姓名(N) | manager | string |
| 直接下属(E) | directReports | string[] |
组织单位(Organizational Unit)常用选项卡中的属性

| 选项卡项名 | 属性名 | 备注 |
| 名称 | name | 在同一节点下唯一,string |
| 描述(D) | description | string[] |
| 国家/地区(O) | co | string |
| 邮政编码(Z) | postalCode | string |
| 省/自治区(V) | st | string |
| 市/县(C) | l | string |
| 街道(S) | street | string |
Active Directory的隐藏通用属性
这一部分属性,在选项卡上是看不到的,必须在【属性编辑器】中才能查看到:
| 属性 | 备注 |
| objectGUID | 全域内唯一,对象创建时自动生成的,16进制所以在DirecotryEntry中接受时要做数据处理。 |
| distinguishedName | 全域内唯一,对象创建或者移动时自动生成。详细请看上章。 |
| objectClass | 对象创建时自动创建 |
| cn | 常用于User或者Computer,与name相同。 |
| ou | 常用于Ou,与name同属性。 |
大约整理出这些常用属性,若想查看更多有两种方式:第一种查看属性的属性编辑器,第二种遍历DirectoryEntry.Properties.PropertyNames;
结语
这些属性根据业务场景不同用的多少也会不同。有时候可能会使用一些不常用的属性存储与业务处理有关的数据,因为AD中的数据存储不想关系型数据库,所以在AD中一些不常用的属性我们会根据不同业务场景去为逻辑变成做铺垫。Filter语法的话其实和LDAP协议有着很密切的关系但这里就不说了。主要是DirectoryEntry和DirectorySearcher这两个类对象,在后面DirectoryEntry做AD编程时将无处不在,它是一个入口。鉴于目前.NET Core 没有更新System.DirectoryServices;。所以以后若使用PowerShell那就另外再说了。
本章最后更新时间:2017年4月23日18:10:13
作者:IFire47 出处:http://www.cnblogs.com/IFire47/
Active Directory的DirectoryEntry与DirectorySearcher初识及Filter语法的更多相关文章
- C# AD(Active Directory)域信息同步,组织单位、用户等信息查询
示例准备 打开上一篇文章配置好的AD域控制器 开始菜单-->管理工具-->Active Directory 用户和计算机 新建组织单位和用户 新建层次关系如下: 知识了解 我们要用C# ...
- C#操作Active Directory(AD)详解
1. LDAP简介 LDAP(轻量级目录访问协议,Lightweight Directory Access Protocol)是实现提供被称为目录服务的信息服务.目录服务是一种特殊的数据库系统,其专门 ...
- 如何通过使用窗体身份验证和 Visual C#.NET 对 Active Directory 验证身份
本分步指南演示如何在 ASP.NET 应用程序如何使用窗体身份验证允许用户使用轻型目录访问协议 (LDAP),对 Active Directory 进行验证.经过身份验证的用户重定向之后,可以使用Ap ...
- 操作Active Directory C#
.Net平台操作活动目录Active Directory,使用System.DirectoryServices.ActiveDirectory,主要是User OU 和Group的操作. 代码运行了一 ...
- Active Directory组织单位(Organizational Unit)操作汇总
前言 本章聊Active Directory的组织单位(OU)的新增.修改.移动等操作,使用.NET Framework 为我们提供的System.DirectoryServices程序集. 不积跬步 ...
- Active Directory的LDAP协议与DN(Distinguished Name)详解
前言 光copy几段代码的文章没什么意思,本章上最基础的代码,主要是为了从编程方面聊LDAP和DN,其它的后面聊,一步步慢慢来吧. Active Directory编程须知 1.域控服务器: Wind ...
- 通过LDAP验证Active Directory服务
原文地址:http://www.byywee.com/page/M0/S215/215725.html C#: using System; using System.Collections.Gener ...
- CAS FOR WINDOW ACTIVE DIRECTORY SSO单点登录
一.CAS是什么? CAS(Central Authentication Service)是 Yale 大学发起的一个企业级的.开源的项目,旨在为 Web 应用系统提供一种可靠的单点登录解决方法(支持 ...
- AD域的安装(在Windows Server 2003中安装Active Directory)
在Active Directory中提供了一组服务器作为身份验证服务器或登录服务器,这类服务器被称作域控制器(Domain Controller,简称DC).建立一个AD域的过程实际就是在一台运行Wi ...
随机推荐
- ACM程序设计选修课——1018: Common Subsequence(DP)
问题 L: Common Subsequence 时间限制: 1 Sec 内存限制: 32 MB 提交: 70 解决: 40 [提交][状态][讨论版] 题目描述 A subsequence of ...
- jquery中append、prepend, before和after方法的区别(一)
原文:http://blog.csdn.net/woosido123/article/details/64439490 在 jquery中append() 与 prepend()是在元素内插入内容(该 ...
- xsy 1845 - GCD
from NOIP2016模拟题34 Description 给定一个长度\(n\le 10^6\)的序列, 给定\(A, B\) 给出一个序列,要求你通过如下两个操作使得序列中所有数的最大公约数大于 ...
- 洛谷P1101 单词方阵
题目描述 给一nXn的字母方阵,内可能蕴含多个“yizhong”单词.单词在方阵中是沿着同一方向连续摆放的.摆放可沿着8个方向的任一方向,同一单词摆放时不再改变方向,单词与单词之间[color=red ...
- 【POJ1144】Network(割点)(模板)
题意:给定一张无向图,求割点个数 思路:感谢CC大神http://ccenjoyyourlife.blog.163.com/的讲解 割点的定义就是某个联通块中删去此点连通性发生变化的的点 有两种割点: ...
- Crash的数字表格 BZOJ 2154 / jzptab BZOJ 2693
jzptab [问题描述] 求: 多组询问 [输入格式] 一个正整数T表示数据组数 接下来T行 每行两个正整数 表示N.M [输出格式] T行 每行一个整数 表示第i组数据的结果 [样例输入] 1 4 ...
- Atcoder CODE FESTIVAL 2017 qual B C - 3 Steps 二分图
题目链接 题意 给定一个无向图,\(n\)个点,\(m\)条边(\(n,m\leq 1e5\)). 重复如下操作: 选择相异的两点u,v满足从点u出发走三条边恰好能到达点v.在这样的u,v点对之间添一 ...
- #pragma用法
#pragma是一种预处理指令,作用是设定编译器的状态或者是指示编译器完成一些特定的动作. 其格式一般为:#pragma Para.其中Para为参数.下面是一些常见用法. 1.message ——在 ...
- php 几种排序模式
冒泡排序 冒泡排序(Bubble Sort,台湾译为:泡沫排序或气泡排序)是一种简单的排序算法.它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来.走访数列的工>作 ...
- PHPCMS内链设置,PHPCMS关联链接设置
需求: 在网站中的关键词,自动加上链接. 在PHPCMS中叫做“关联链接”,在DEDECMS中叫做TAG标签. 第1步:后台 -> 扩展 -> 关联链接 -> 添加关联链接: 第2步 ...