System.DirectoryServices
是一个命名空间,包含允许我们从托管代码访问活动目录的类和方法。这个名称空间的核心组件是目录尝试和目录射手类;接下来,我们将特别关注这些类中的每一个,提供更多关于它们的方法的信息,更重要的是,它们的核心功能。这两个类都使用 ADSI 技术,并且都可以与任何活动目录域服务提供商一起使用。目前的提供商有互联网信息服务(IIS)、轻量级目录访问协议(LDAP)、Novell NetWare 目录服务(NDS)和 WinNT。
您可以使用目录搜索对象来搜索和执行对任何符合 LDAP 的服务器的查询,特别是对活动目录域服务的查询。LDAP 是 ADSI 提供的唯一支持目录搜索的系统提供商。创建目录搜索程序时,指定要检索的根目录和可选的要检索的属性列表。该任务由 SearchRoot 属性执行。
SearchRoot 属性使您能够设置其他属性来执行以下任务:
- 在本地计算机上缓存搜索结果。将 CacheResults 属性设置为 true,以在本地计算机上存储目录信息。只有当目录尝试时,才会对此本地缓存进行更新。调用 CommitChanges 方法。
- 使用服务器时间限制属性指定搜索时间长度。
- 仅检索属性名。将属性名称仅属性设置为真,仅检索已赋值的属性名称。
- 执行分页搜索。设置页面大小属性,指定页面搜索中返回的最大对象数。如果不想执行分页搜索,请将 PageSize 属性设置为零(这是默认设置)。
- 使用大小限制属性指定要返回的最大条目数。如果将大小限制属性设置为默认值零,则服务器确定的默认值为 1000 个条目。
| | 注意:如果返回条目的最大数量和时间限制超过了服务器上设置的限制,服务器设置将覆盖组件设置。 |
FindOne 方法执行搜索,只返回找到的第一个条目。如果在搜索过程中找到多个条目,则只返回第一个条目。如果没有找到符合搜索条件的条目,将返回空引用。
FindAll 方法执行搜索并返回找到的条目的集合。然而,由于我们可以处理的提供商的多样性,这一操作有可能无法成功完成;在这种情况下,将引发 NotSupportedException。另一个不成功的场景是当我们试图在不是容器的对象中执行搜索时;在这种情况下,FindAll 方法会引发 InvalidOperationException。
此属性表示客户端等待服务器返回结果的最长时间。如果服务器在此时间内没有响应,搜索将中止,并且不会返回任何结果。
此属性获取或设置一个值,该值指示服务器用于搜索的最长时间。如果达到时间限制,则只返回在该时间点之前找到的条目。
此属性是字符串的集合(确切的类型名称是 StringCollection),它获取一个值,该值指示搜索期间要检索的属性列表。
此属性获取或设置一个值,该值指示搜索是否还应返回与搜索筛选器匹配的已删除对象。如果您不知道广告中的对象是否已被删除或仍然存在,此选项会非常有帮助。
您可以使用目录尝试类绑定到活动目录对象,以利用读取和更新属性等功能。这个类以及一些帮助类为生命周期管理和导航方法提供了支持。
生命周期,我们指的是子节点的完整管理(创建、删除、重命名和移动);您还能够枚举一个节点的所有子节点。当您考虑一组对象(如用户、计算机或打印机)时,这很有用。为了将更改传播到广告树,您必须提交您的更改。与我们的案例场景(阿尔法数据公司)一样,现实世界中的公司正在不断扩张,向他们的森林或域中添加新的员工或计算机;ADSI 技术提供了以编程方式将这些对象添加到目录树的方法。
要在层次结构中创建目录条目,请使用 Children 属性。Children 属性是一个集合,它提供了一个 Add 方法,通过该方法可以将节点添加到集合中当前绑定到的父节点的正下方。
向集合中添加节点时,必须指定新节点的名称以及要与该节点关联的架构模板的名称。例如,您可能希望使用名为“计算机”的模式将新计算机添加到层次结构中。此类还包含属性缓存,这对于优化网络流量非常有用。要使用属性缓存,请参见 UsePropertyCache 属性。
此方法将对目录条目所做的更改保存到基础目录存储中。
| | 注意:如果在调用 CommitChanges 之前调用 RefreshCache,对属性缓存的任何未提交的更改都将丢失。 |
|
| 提示:使用目录服务会话类来读取、写入、删除、更改和添加到活动目录域服务层次结构。关联枚举:目录服务授权访问。 |
CopyTo 方法的第一个重载只接受另一个 DirectoryEntry 作为参数,它创建此条目的副本作为指定父条目的子条目。第二个重载将字符串作为参数,指定新复制的节点的名称。此方法返回复制的目录尝试的实例,并在要复制到的指定目录尝试不是容器的情况下引发无效操作异常。为了反映您对广告树的更改,您必须调用 CommitChanges 方法。
此方法从活动目录域服务层次结构中删除条目及其整个子树。在活动目录服务接口(ADSI)系统提供的提供程序中,目前只有轻型目录访问协议(LDAP)支持此操作。
这些方法用于从托管代码中调用本机方法或 getter 和 setter 属性。
- Invoke 方法采用要调用的方法的名称和定义列表的对象数组作为其参数。
- InvokeGet 方法获取您想要获取其值的属性的名称(字符串形式)。
- InvokeSet 方法的不同之处仅在于方法坚定;它处理一个对象数组,这些对象用作您指定的属性的可能值。
如果失败,调用方法可能会抛出两种类型的异常。第一个是目录服务异常,当本机方法抛出 COMException 时。第二种是 TargetInvocationException,当本机方法引发 TargetInvocationException 异常时。InnerException 属性包含一个 COMException,它包含有关实际发生的错误的信息。
像复制到方法一样,移动到方法有两个重载。第一个只接受一个目录尝试,只需将调用目录尝试移动到作为参数传递的目录尝试中。第二个重载像在 CopyTo 的情况下一样,接受一个字符串参数,该参数指定要在新的 DirectoryEntry 父级中使用的名称。如果作为参数传递的 DirectoryEntry 不是容器,MoveTo 方法会抛出一个invalid operationexception。
重命名方法更改此目录对象的名称。
搜索结果类封装了活动目录域服务层次结构中的一个节点,该节点在通过目录搜索程序进行搜索时返回。SearchResult 类的实例与 DirectoryEntry 类共享一种类似的方法来访问对象属性。最重要的区别是,每次访问新对象时,目录尝试类都会从活动目录域服务层次结构中检索其信息,而搜索结果的数据已经在搜索结果集合中可用,它是从使用目录搜索类执行的查询中返回的。只有那些通过目录服务器指定的属性。查询中的属性加载集合可从搜索结果中获得。
获取此搜索结果的路径。路径属性在活动目录域服务层次结构中唯一标识此条目。始终可以使用此路径检索条目。
这将获取此对象的属性的 ResultPropertyCollection 集合;当然,这个集合只包含通过 directory archer . properties to load 显式请求的属性。ResultPropertyCollection 继承自 DictionaryBase 类,因此可以在 Item 属性的帮助下使用符号访问其成员。在 ResultPropertyCollection 中,我们还有一些字段可以用来获取字典中包含的项目数,所有的属性名(之前是通过 DirectorySearcher 指定的。属性加载)、键和值。
从活动目录域服务层次结构中检索与搜索结果对应的目录尝试。
| | 注意:对通过目录服务返回的每个搜索结果调用 GetDirectoryEntry 可能会很慢。 |
搜索结果集合类包含活动目录层次结构在目录搜索查询期间返回的搜索结果实例。因为它继承自集合,所以它具有 Count 和 Item 属性,这两个属性分别表示集合中包含的项数和集合中的项本身(给定有效的索引)。即使在 SearchResultCollection 内部,使用属性加载字段,我们也可以获得在 directory archer . properties to load 中显式指定的属性列表。
| | 注意:由于实现限制,当垃圾收集时,SearchResultCollection 类无法释放其所有非托管资源。为了防止内存泄漏,当不再需要 SearchResultCollection 对象时,必须调用 Dispose 方法。 |
UserPrincipal 类封装了作为用户帐户的主体。我们可以将主体定义为 AD 对象。我们可以使用这个类来表示一个用户对象,从更通用的类目录开始。UserPrincipal 类有一个主构造函数,它将 PrincipalContext(参见下一章)的引用作为输入,在它的变体中有一个用户名、一个密码和一个布尔标志。
用户主体类包含在系统中。目录服务.账户管理命名空间。
用户主体类公开了一些非常有用的静态方法,允许我们基于特定的属性或条件执行搜索操作。所有这些静态方法都将 PrincipalContext 对象、定义搜索条件的 MatchType 标志以及因方法而异的第三个参数作为参数;其中一些解释如下。
此方法搜索在指定为参数的日期时间范围内有错误密码记录的用户;匹配的类型可以使用 MatchType 枚举来定义。如果找不到结果,此方法将返回一个空的 user principal resultcollection。
此方法在给定日期时间范围的情况下,返回用户主体的 PrincipalSearchResult 对象,该对象的帐户到期日期满足匹配类型枚举所施加的筛选。
对于帐户锁定时间在指定日期和时间范围内的用户,该方法返回用户主体的主用户结果对象。即使在这种情况下,匹配类型属性定义了搜索条件,如果结果为零,将返回一个空集合。
此方法返回用户主体对象的 PrincipalSearchResult 集合,这些用户的帐户登录记录在指定的日期和时间范围内。
除了这些静态方法之外,UserPrincipal 类使我们更容易对用户对象执行操作,例如更改/终止他们的密码、检查组成员资格以及列出组成员资格。此外,UserPrincipal 类以更面向对象的方式封装了用户对象的属性 getter。
| | 注:关于 UserPrincipal 类的更多信息可以在官方 MSDN 页面的中找到。 |
此类封装了执行所有操作的服务器或域、用作这些操作的基础的容器以及用于执行这些操作的凭据。这个类本身不公开任何特定的方法或属性,但是它有一个有价值的方法,可以声明一组凭据(用户名和密码)是否有效。这种验证是通过执行对服务器的连接请求来执行的,该连接请求在方法的签名中被指定为参数。
PrincipalContextprincipalContext = null;
try
{
principalContext = new PrincipalContext(ContextType.Domain, IP_PORT, "CN =Users,DC=alphadata,DC=adds");
bool isValid = principalContext.ValidateCredentials("user", "pwd");
}
catch (PrincipalException e)
{ Console.WriteLine("Failed to create PrincipalContext. Exception: " + e); return; }
上下文类型参数可以是机器、域或应用程序目录。请注意,由于可能会引发 PrincipalException(例如,当与服务器的连接不成功时),所以一切都被包装在 try-catch 子句中。 IP_PORT 参数是一个常量,包含广告服务器的本地 IP 地址和 LDAP 端口(389)。
由于 AD 允许我们管理组和计算机,系统。AccountManagement 命名空间提供了两个从名为 Principal 的抽象类继承的类来管理它们。这些类是 GroupPrincipal 和 ComputerPrincipal,正如我们在 UserPrincipal 类中看到的,它们的主要功能是以一种更简单、更面向对象的方式包装 AD/DirectoryEntry 对象。在这种情况下,它可以是一个组或一台计算机。根据类引用的对象类型,您可以公开不同的方法和属性。注意到 GroupPrincipal 和 ComputerPrincipal 都继承自与 UserPrincipal 相同的基类这一事实,我们将不继续描述它们的公共(和静态)方法,因为它们是相似的,并且在某些情况下与本章前面讨论的方法相同。
| | 注意:如果您想详细了解 GroupPrincipal 和 ComputerPrincipal 类,请参考以下链接:group principal:http://msdn . Microsoft . com/en-us/library/system . director yservices . account management . group principal(v = vs . 110)。aspxcomputer principal:http://msdn . Microsoft . com/en-us/library/system . director yservices . account management . computer principal(v = vs . 110)。aspx |
当使用静态方法在 PrincipalContext 中执行查询时,有必要指定一个特定的标志来定义我们要考虑的匹配类型。下表列出了匹配类型枚举的所有可能值。
成员名称 | 描述 |
---|---|
等于 | 搜索结果包括与提供的值相等的值。如果提供的值指定了日期和时间,则返回的集合包括具有相同日期和时间的对象。 |
大于 | 搜索结果包含的值大于提供的值。如果提供的值指定了日期和时间,则返回的集合包括日期在指定日期和时间之后的对象。 |
更大的需求 | 搜索结果包括大于或等于提供值的值。如果提供的值指定了日期和时间,则返回的集合包括日期在指定日期和时间或之后的对象。 |
少于 | 搜索结果包括小于提供值的值。如果提供的值指定了日期和时间,则返回的集合包括日期早于指定日期和时间的对象。 |
至少同等 | 搜索结果包括小于或等于提供值的值。如果提供的值指定了日期和时间,则返回的集合包括日期早于或等于指定日期和时间的对象。 |
注意质量 | 搜索结果包含的值不等于提供的值。如果提供的值指定了日期和时间,则返回的集合包含不包含指定日期和时间的对象。 |
表 3:匹配类型枚举的成员列表