下载第 21章 ADSI和 AD介绍本章讨论活动目录服务接口 (Active Directory Services Interface,A D S I )和活动目录 ( A c t i v e
D i r e c t o r y,A D ),以及怎样用 A S P访问目录服务和使用它们所包含的信息。这里的目录和目录服务实际上是指一种特定的数据库,该数据库能够有效地查找像网络资源目录一类的信息。
A D是一种网络资源的目录,而 A D S I是能够访问任何目录的 M i c r o s o f t技术。其他公司也有类似的技术,例如 S u n公司的 J N D I,但因本书是针对 Wi n d o w s的,所以在此只讨论 A D SI。
不要混淆 A D S I和 A D,它们是两种截然不同的技术。尽管如此,因为这两种技术确实是密切地相互作用,我们还是将它们放在同一章里讨论。 A D是随 Windows 2000诞生的大而新的目录,包含了所有的安全性和管理本地网域所需要的其他信息。另一方面,A D S I是一套
M i c r o s o f t作为访问任何目录的方法而推出的 C O M接口,这意味着 A D S I也是访问 A D的通常方法。尽管 A D只存在于 Windows 2000 Server和 Windows 2000 Advanced Server中,A D S I却适用于所有的 3 2位操作系统,Windows 2000 Professional,NT 4.0和 Windows 9x。
本章的目的是使读者掌握怎样用 A S P语言简单而又容易地访问目录,因此本章重点是
A D S I,但由于 A D的重要性,本章也将接触到 A D的一些相关功能。
本章只讨论了 A D S I的基础,如果想更深入地研究,请查阅,Professional ADSI
P r o g r a m m i n g》一书,Simon Robinson著,Wrox Press出版。
21.1 ADSI的用途这里有两个相关联的问题。前面讲过 A D O,在技术上 A D O符合 M i c r o s o f t的 U D A规范,本书第二部分里已深入讨论过。 A D O能访问任何有 OLE DB提供者的数据源。目录是另一种类型的数据源,为了使用目录,必须使用一种不同的技术 — A D S I。为了理解为什么要使用
A D S I,需要理解是什么使目录不同于一般的数据源,以及 A D S I能做哪些 A D O不能做的事。
A D O的确是一种通用的技术。原理上,M i c r o s o f t的目的是让 A D O可以访问任何数据源,
而不管这数据源的内部结构。但又在本质上重视关系型的数据源。这没有什么错,但这也确实意味着如果想访问分层结构的数据源,A D O可能不总是最有效的办法。因此引入 A D S I,因为 A D S I正是专门为分层结构数据源而设计的。精心设计的 A D S I使用户在浏览树状结构时感到比较容易,而 A D O就没这么轻松。
上面提到的分层结构的数据源和目录,它们是一回事么?它们相似,但不完全相同。下面先讨论相同点,即它们都是树状结构,再讨论目录区别于数据库和其他数据源的特征。
分层结构的数据源是按树状结构组织起来的,对象包含着其他对象,与 Wi n d o w s
的文件系统中的文件夹包含文件和文件夹一样,而多数目录也是这样的结构。
事实上,体会这一点最简单的方法是快速浏览 A D的结构。图 2 1 - 1是从 a d s v w,e x e中截取的,
a d s v w,e x e是一个通用目录浏览器,可用于任何基于 A D S I的目录 (包括 A D )。 a d s v w,e x e是由
ADSI SDK提供的。
图 21-1 A D的结构图 2 1 - 1中有很多我们将研究的内容,我们在后面再回来讲述,如果现在不能全看懂也不必担心。请注意左边的树状结构,它是一个标准的树控件,清楚地显示了 A D中数据的分层排列。以 CN = Simon Robinson为例,这是作者在局域网上的帐号,它的父级是 CN = Users。在目录用语里,父子关系称为包含关系。 CN = Users称为一个容器,包含了 CN = Simon
R o b i n s o n对象。在这个 A D中,CN = Users实际上包含了此域中所有的用户帐号,不过实际情况不总是这种。
同样,用户容器也被代表域的对象 DC = To p O f T h e P o p s包含着。 D C = To p O f T h e P o p s容易让人误解,因为域的全名是 DC = TopOfThePops,DC=Fame,DC=com,对应于一个虚拟的
U R L,To p O f T h e P o p s,F a m e,c o m ( Windows 2000支持这样的域名,而任何 NT 4.0机器只能识别第一部分 To p O f T h e P o p s )。不要为这些名字的格式而担心,这是 A D专用的,你很快就会适应,
C N代表普通名 (Common Name),而 D C代表域组件 (Domain Component)。
最后,树中的域节点被 L D A P对象包含。 L D A P代表轻量目录访问协议 ( L i g h t w e i g h t
Directory Access Protocol),这是一个访问目录的工业标准协议,该协议的引入表明了 A D是与
L D A P相联系的。后面将进一步讨论 L D A P。
迄今为止,所做的工作是指出我们正在存储大量的对象信息,并正在以分层方式管理这些信息。顺便提一下,这里所说的对象是通常意义下的,不是技术上的,在这里不指 C O M对象。 A D提供了一个非常好的例子,展示了 A D S I所能访问的目录的结构。下面将探索 A D的细节,并且演示目录的典型结构。然后,就可以学习如何用 A D S I去得到和修改目录中的信息。
但首先,来看一下如何获得所需的软件。
21.2 必需的软件在这一节中,由于 A D S I和 A D需要的软件不同,我们将分别讨论它们。
Windows 2000集成了 A D。如果你的计算机运行在 Windows 2000下,并将其作为域控制器,则已经安装了 A D,反之则不会。关键在于是否把 Windows 2000作为域控制器。如果在一个域内的 Windows 2000工作站,由一个 NT 4.0主域控制器控制,也不会有 A D。
616计计 ASP 3 高级编程 下载
A D S I也是 Windows 2000操作系统 ( P r o f e s s i o n a l或 S e r v e r )中的一部分,但能够从 M i c r o s o f t的 We b
站点上下载用于 NT 4.0和 Windows 9x的 A D S I。另外,可能需要 ADSI SDK来开发软件。无论正在用什么操作系统,都需要下载这个 S D K。它包含了各种各样的头文件和文档。尽管编写 A S P客户程序时,它不如用 V B或 C + +编程时那么必需,但它包含了图 2 1 - 1中使用的 a d s v w,e x e实用程序。
下面将使用 a d s v w,e x e进一步研究 A D。 a d s v w,e x e也叫做活动目录浏览器 (Active Directory
B r o w s e r ),这名字有些误导作用。这是一个通用的目录浏览器,可以检查任何 A D S I兼容的目录,而不只是 A D。活动目录浏览器是一个好工具,因为其本身使用 A D S I搜集信息,并显示给我们。因此,我们看到的信息的格式恰恰就是用 A D S I编程时所需要的。
正如前面提到的,a s d s v w,e x e是 ADSI SDK的一部分,可以从微软的 We b站点上下载。如果没有的话,我们建议下载一个拷贝,你会发现对于研究目录,它是非常有用的。
21.3 AD的内部结构
A D包含了一个域控制器管理一个域所需的全部信息。从这个意义上讲,它与 NT 4.0服务器中的域目录 (domain directory)是一样的。所不同的是它符合 L D A P标准。因为 L D A P是工业标准,所以很容易编写用标准 A P I函数 (包括 A D S I )来访问 A D的客户程序。相比之下,NT 4.0
上相应的数据库却是 M i c r o s o f t专用的,通过 Windows API函数只能得到少得可怜的信息。实际上,根本不能把该数据库用作集中管理网络资源的目录,但 A D可以。
另外,A D远比原有的 NT 4.0域目录强大。它连同 Windows 2000一起,支持下列概念:把域本身排列成域树 (domain tree),或允许很多独立的树共享配置数据,形成一个域林 ( d o m a i n
f o r e s t )。还允许把个人的信息像操作系统使用的资料一样存储进去。
就 A D中存储的信息而言,实际上有两个部分。缺省情况下,A D包含了管理一个域所需要的全部信息,如计算机、用户和工作组帐号,以及相应的安全权限。另一方面,A D被设计成通用的目录,这意味着任何其他系统管理员认为有用的内容都可存入 A D。所以像用户帐号这样的信息也可能出现在薪金明细和公司组织结构下面。 A D还有一套非常完善的安全系统,
由管理员分配细致的等级,决定谁具有对各式各样信息的读或写的权力。
但是,令我们最感兴趣的还是 A D的整体结构,我们将给出一个一般目录的例子。
21.3.1 目录里的对象和属性需要理解的第一件事情是:关系型数据库把数据存储在表的行和列里,而在目录里一个很重要的概念是对象,对象含有需要存放的信息。在图 2 1 - 1的屏幕截图中,我们就选了一个用户帐号的对象。 A D中的其他对象包括计算机、域和工作组等。稍后,当我们讨论 Wi n N T
A D S I提供者时将要碰到其他目录里的对象,如服务对象和打印队列对象等。
不要把目录中的对象与 C O M对象 (组件 )相混淆,目录里的对象与 C O M毫不相干。
它们有属性,但通常不具有方法。
实际上目录中通常除了对象没有别的,对象被排成层状。对象可被认为是由许多属性组成的。
注意在这里我们不是在讨论 C O M自动化属性,仅仅是在讨论一条条的信息。一个属性包括属性名和属性值。例如,上例中在 A D中的用户帐号的属性如表 2 1 - 1所示。
第 2 1章 A D S I和 A D介绍 计计 617下载表 21-1 示例对象的属性及其值属 性 名 属 性 值
C N Simon Robinson
A D s P a t h LDAP://CN=Simon Robinson,CN=Users,DC=TopOfThePops,DC=Fame,DC=com
s A M A c c o u n tNa m e s i m o n
D e s c r i p t i o n 一段注释,可用 a d s v w,e x e设置
M a i l s i m o n @ s i m o n r o b i s o n,c o m
以上这些属性大部分是不言而喻的。 C N代表普通名 (Common Name),是访问对象时的通常名字。 A D s P a t h是使用 A D S I访问目录时,可唯一确定该对象的名字,很像一个文件的完整路径名,包含了该对象本身和目录树中所有在其上面的对象的名字。 s A M A c c o u n t N a m e是用户在域中以这个帐号注册时的提供名字。
表 2 1 - 1展示的一个重要概念,就是一个属性有两个部分:名字 (如 C N )和值 (如 S i m o n
R o b i n s o n )。更准确地说是一个名字和一个或一个以上的值,因为有些属性是多值的。可把多值性想成一个值的数组。
顺便说一下,表 2 1 - 1只是属性中的一小部分,如果安装了 A D,在查看你自己的用户帐号时,
将发现数量巨大的属性。其中许多还没有值,只是为某些系统管理员偶尔的需要而准备的。
当使用 a d s v w,e x e时,可用屏幕右边的 Properties 列表框查看不同属性 (见图 2 1 - 1 )。
选中一个属性,它的值就在旁边的文本框中显示出来。如果想改变这个值,就在文本框中输入一个新值并单击列表框下面的 C h a n g e按钮。再点击 A p p l y按钮确认。
21.3.2 对象的类到目前为止,我们已使用 a d s v w,e x e查看了用户帐号的对象,别忘了还有其他类的对象,
例如专门针对计算机的对象。从这种意义上,一个用户和一个计算机 (对象 )的不同之处就是它们属性的数目和类型的不同。例如,选中图 2 1 - 2所示的这个对象。
图 21-2 计算机对象这是描述作者所在的域的域控制器的对象,这是一台名叫 B I G G Y B I G G Y的计算机。它表
618计计 ASP 3 高级编程 下载示一台计算机,如果要检查它的属性,就会发现它的很多属性与用户对象的一样,当然还有其他一些属性,这些属性包含只属于计算机的信息。
对象的类型称作类。例如,在 A D里,用户是对象类,计算机也是对象类。因用户和计算机是两个不同的类,所以它们能拥有的属性就不一样。在 a d s v w,e x e里,选中的对象的类显示在右边顶上的信息中,在图 2 1 - 1和图 2 1 - 2中都可看见。
类决定了对象拥有什么样的属性,特别是它决定了必有的和可选的属性。必有属性
(Mandatory propertie)是某类中所有对象都必须有值的属性,可选属性 (Optional propertie)的值可能有但不是必须有。一个对象通常除了具有类所定义的必有属性和可选属性之外,再无其他属性。
21.3.3 容器和叶前面已提到,目录树中可作为其他对象的父对象的是容器。而不能这么做的则是叶 ( l e a f )。
一个对象是容器还是叶决定于它所属的类。一些类定义为容器而另一些类则定义为叶。例如,
在 A D里,用户和计算机都是容器。图 2 1 - 1和图 2 1 - 2中的信息中的两行说明了这一点。
C o n t a i n e r行说明它是不是一个容器,C o n t a i n m e n t行说明它可成为哪些类对象的父对象。
这类事情在大多数目录中被定义得很仔细,以确保用户在修改目录的内容时不会破块目录树的结构。如果往目录中添加新的对象,必须把它放在规定的地方,符合目录规则,即哪些类的对象能包含哪些类的对象。当然还有其他的检查,如是否有足够的安全权限!
事实上一个对象是容器并不是说它必须包含其他对象,而仅仅从原则上允许这么做而已。
例如,在 A D里,所有用户帐号从技术上说都是容器,但在作者的用户帐号里,恰巧什么也不包含。
同样,你可能已经注意到目录结构和 Wi n d o w s的文件系统很类似。它们都是同一种层式结构,文件夹在 Wi n d o w s里有时候也称为目录 (这种称呼是从 U N I X系统移植而来的 )。按照这种相似性,文件系统里的文件夹对应目录里的容器,而文件系统里的文件对应目录里的叶对象。但当心不要把这种相似性推得太广。在文件系统中,文件夹的作用仅仅是文件的容器,
除了 Wi n d o w s自动赋予的特定的系统属性 (如创建日期等 )和关于谁能访问它们的安全信息外,
并不真正拥有自己的数据。不能像往文件里存东西那样往文件夹里存大量的文本。相反,在目录里,容器本身也是目录对象,有自己的一套属性。容器与叶唯一的不同之处就是容器可以包含其他的对象。
21.3.4 模式上面已看到了如何通过类来定义对象,以及怎样确定一个对象能拥有什么样的属性和是否是一个容器。这些规则连同其他相关信息,如属性的数据类型 (例如,普通名是一个字符串并且是单值的 ),以及其他任何关于值的范围的限制,并称为模式 ( s c h e m a )。需要说明的是,
模式本身就存储在目录中。可能认为模式是目录的内部细节,且它的实现是目录的事。从某种程度上说这是对的。但有标准的途径去访问模式,这需要模式本身作为目录的一部分存储。
在 A D里,模式被存储在 A D s P a t h为 LDAP://CN=Schema,CN=Configuration,<domain
n a m e >的容器中,这里 domain name是用 A D的格式表示的用户的域名 (见图 2 1 - 2所示的屏幕截图 )。如果检查这个容器,将看到图 2 1 - 3所示的屏幕截图。
第 2 1章 A D S I和 A D介绍 计计 619下载图 21-3 存放模式的容器对象这个对象包含了描述模式的所有对象。从目录树栏的滚动条的长度可以看出,有数目庞大的对象,这是由于 A D有很多属性和类。往下滚动一点并选择描述计算机的模式项,将会看到图 2 1 - 4所示的屏幕截图。
图 21-4 描述计算机的模式
CN = Computer对象说明 C o m p u t e r类的所有实例在目录里应是什么样,这也是它自己的类标识为 c l a s s S c h e m a (类模式 )的原因,它为一个特定的类定义模式!树控件中的其它大多数对象是 a t t r i b u t e S c h e m a (属性模式 ),这意味着它提供了有关某具属性的信息,如它的值的数据类型和是否是多值的。
设置 P r o p e r t i e s列表框来看看 m u s t C o n t a i n属性。这是一个多值的属性,列出了计算机类所有必选的属性的名字。另一属性 m a y C o n t a i n列出了计算机所有的可选属性。
奇怪的是,图 2 1 - 4中的错误消息 E _ A D S _ P R O P E RT Y _ N O T F O U N D说明 m u s t C o n t a i n并不包含任何内容。而在我安装的 A D里,对这个 c l a s s S c h e m a对象,m a y C o n t a i n也给出相同的错误消息。这有点奇怪,因为我们已经看到计算机拥有很多属性。这个表面上的矛盾引出了类的一个重要概念:继承 ( i n h e r i t a n c e )。
21.3.5 继承目录里的类可相互派生 ( d e r i v e )。
如果对 C O M有一定的使用经验,那么你也许已经知道一个接口可从另一个派生。如果接口 A从接口 B派生,那么 A拥有 B的所有属性和方法和 A自己附加的属性和方法。所有 C O M接口都显露三个方法,Q u e r y I n t e r f a c e,A d d R e f和 R e l e a s e,因为它们都由 I U n k n o w n派生。
如果你曾经用 C + +或 J a v a编过面向对象的程序,也许已经接触过类的继承,这与刚才讲到
620计计 ASP 3 高级编程 下载的是一回事。如果类 A从类 B派生,则类 A实现类 B的所有成员函数和成员变量并有属于它自己的成员函数和成员变量。
上述原则同样适用于目录的类,如果类 A是 B的继承类,那么实例 A可以具有实例 B的
c l a s s S c h e m a对象中所定义的必选和可选属性 (注意,这里用了“可以”这个词,但对于必选属性,用“必须”或许更恰当 ),还有 A自己的 c l a s s S c h e m a对象中的那些属性。
可以通过已有的类来生成新类。在 C + +里,甚至允许有抽象类 ( a b s t r a c t ),这些类是专门为派生而定义的。实际上抽象类是不能真正创建它的对象的。 C + +程序员将看到目录中的抽象类与 C + +里的抽象类作用相同。
这解释了 a d s v w,e x e屏幕右边上方标记为 Derived From的行。这行给出了当前被查看的对象的类的父类的名字。观察图 2 1 - 4,会发现类 c l a s s S c h e m a和 d M D (包含所有模式项的对象的类 )都是从一个名叫 t o p的类派生的。 C o m p u t e r类是从 U s e r类派生的 (听起来有奇怪,
但这是有意义的,因为 C o m p u t e r类需要实现 U s e r类的几乎所有的属性 ),而 u s e r 是 从 包 含 了 针 对 一 般 人 的 更 广 义 的 信 息 的
o rg a n i z a t i o n a l P e r s o n类派生的。
事实上,就 A D而言,可以更深入一些。在 A D (就这问题而言,
可以是任何符合 L D A P 的目录 )里的所有对象都有一个名叫
o b j e c t C l a s s的属性。它是多值的,它的值是继承树中通往这个类的所有 (祖先 )类的类名。对于一个 C o m p u t e r类,其类链如图 2 1 - 5所示。
如果在 A D浏览器里的 P r o p e r t i e s列表框中选择 o b j e c t C l a s s项,
将看到这一点,如图 2 1 - 6所示。
图 21-6 在目录浏览器中显示的类链
t o p类在 A D里起着重要的作用。这是一个通用的类,有数目庞大的必选和可选的属性。
M i c r o s o f t认为它对 A D中的所有对象都有用。任何符合 L D A P的目录中的所有对象归根结底都是从 t o p类派生的。
到目前为止,你已经获得了关于目录结构的很多信息,这些信息将来我们都需要。现在再进一步讲一下目录,以避免不明白图中列出的其它部分是干什么的。 C L S I D是一个唯一的
G U I D (用来标识对象的类 )。标识为 Primary Interface的行是与 A D S I有关的,与 A D无关。使用
A D S I时,你会发现需要创建 C O M组件来访问目录对象,一个 C O M组件对应目录里的一个对象。因为正在讲述 A S P,所以仅使用 A S P里的 I D i s p a t c h接口与 C O M对象通信。 P r i m a r y
I n t e r f a c e是 C O M对象的“真正的”接口的 I I D,也就是当用 V B或 C + +编程时可能直接使用的接第 2 1章 A D S I和 A D介绍 计计 621下载图 21-5 目录中的类链口,用 V B或 C + +编程时避免使用 I D i s p a t h。
帮助文件名和环境提供了类对象的帮助信息。 O I D (对象标识符 )是另一个唯一标识符,不仅标识类,还标识其他信息,如定义这个类的组织的名字。我们并不需要关心对象标识符。
21.4 目录的特征对 A D的结构我们已有一些概念。前面所讲的有的部分是 A D特有的,有的部分不是 A D特有的,而是所有符合 L D A P标准的目录所具有的。对于前面所讲的一切,一般来讲,如果不是实现细节,则大多数目录都满足。
到目前为止,我们已经知道目录是一个分层的信息库,而且知道它包含着对象,对象包含着很多属性。
还有其他一些大多数目录的典型特征。
21.4.1 优化查找目录的主要目的是当需要时可以到它里面去查信息。因此,通常是按读操作的最优化实现的。这基于经常地读目录而不是写目录的假设。 A D正是这样优化的。
21.4.2 查找功能前面所有的屏幕截图演示的都是浏览操作,也就是看看目录中不同的容器里有什么内容。
更经常的情况是进行查找。查找就是根据一个对象的一个或多个属性找出它在目录中的位置。
例如,可能需要找出所有的两个月没有注册的用户帐号以禁用它们。尽管从屏幕截图中已经看到,所有的用户帐号恰好全部存在于 A D的同一个容器里,但要知道,实际不总是这种情况,
通常要执行一下查找操作以确定已找到了所有的用户帐号。
目录一般支持非常复杂的查找请求。找出所有的两个月没有注册的用户帐号只是一个很简单的请求。一个更复杂的请求可能是:显示注册名以,a”开头、两个月没有注册的除域管理者以外的所有用户帐号。所有符合 L D A P标准的目录,包括 A D,都支持这种复杂级别的请求,这使查找成为一个非常强大的概念。
21.4.3 开放性这意味着目录可以通过某一标准协议集进行访问。最常用的是 L D A P协议。通过开放的标准协议使目录具有可访问性,这使得编写与它通讯的客户端应用程序十分容易,可以不需要去学习那些厂家专有的 A P I。
A D符合 L D A P标准,并且随着学习 A D的不断深入,你会发现如何构造和访问数据是非常重要的。 A D有很多的特性,这些特性都是 L D A P需要的。
21.4.4 事务处理很多商业数据库有相当完善的支持事务和当操作失败时回滚事务的功能。 SQL Server属于这个范畴。 A D O包括支持事务的方法,前提是数据源实现事务。在这里提到这个问题的原因是事务处理在目录里通常并不是至关紧要的。
622计计 ASP 3 高级编程 下载
21.4.5 复制检查一个软件是否有用的通常方法是看能否在企业环境具有可扩展性,目录也是如此。
很多目录 (包括 A D )支持可扩展性的方法之一是允许它们自己被复制。换句话说,可以将目录拷贝到多台机器上。对于 A D,任何一个是域控制器的计算机都将存储一份 A D的拷贝。
有一个问题摆在我们面前:怎样确保不同拷贝里的内容是一致的。这问题也将潜在地引发大量的网络数据流,因为每个拷贝都试图使自己保持与其他拷贝一样。的确,如果不小心,
由这个问题产生的网络数据流可能会很容易将复制的初衷 (可扩展性 )破坏掉。
为解决这个问题,可借助于目录的另一个特性。前面已提到,完善的事务处理并不是目录最优先考虑的。现在需要增加一点,当目录里同步不同的拷贝时,只要更新最终被执行了就可以了。设计时 A D就是这个观念。一份拷贝中允许有过时信息,但将在一段时间后与最新的版本同步。 A D执行一些完善的算法来确保这一点。
21.5 常见目录以上讲了 A D是什么和能做什么。下面介绍通常使用的可由 A D S I访问的其他目录。
21.5.1 Netscape目录服务器这是个可从 N e t s c a p e公司得到的通用的 L D A P目录。这里的“通用”,意思是可以存储任何内容。它是按具有高度可扩展性、分层数据存储、按读操作优化的原则设计的,而且有一个只有少量限制 (为维护与 L D A P的兼容 )的模式,你完全可以自己定义。
21.5.2 IIS元数据库这是互联网信息服务器 ( I I S )的配置数据的数据库。可通过 A D S I访问它和 We b站点上所有虚拟目录的细节。然而,元数据库 ( m e t a b a s e )却不遵从 L D A P标准。
21.5.3 Exchange Server目录和站点服务器成员目录之所以把这二者放在一起是因为它们很快将与 A D合并,将不再把它们作为分离的目录。
它们都是符合 L D A P标准的。 Exchange Server目录提供如地址和分布列表等信息给 E x c h a n g e
S e r v e r,而站点服务器成员目录存储了标识访问过该站点的用户的数据,用于产生为这些用户定制的网页并提供专门的安全性支持。
21.5.4 Netware 目录服务这是 A D在 N o v e l l网里的等价物,像 A D一样存储了用户帐号、网络资源和安全权限等信息。
但是,它不遵从 L D A P标准。
21.5.5 Wi n N T
我把它放在最后,严格说来它根本就不应该在这个列表里。 Wi n N T是一个虚构的目录,
是作为 A D S I提供者注册的 C O M组件集。换句话说,它允许通过 A D S I存取目录。这些组件搜集网络中用户和计算机帐号的信息以及在不同机器上运行的服务。这些信息被汇集起来并发第 2 1章 A D S I和 A D介绍 计计 623下载送给客户端,好像它是一个单独的目录。
这有两个理由。首先,考虑到很多网络用的还是 NT 4.0域控制器,而且其中很多在一定时间内还不能升级到 Windows 2000(发布 A D S I和 Windows 2000之间有着 1 2个月的间隔 )。很显然,如果这些系统里的用户使用脚本语言和自动化 C O M组件,他们不能访问 A D提供的用于访问域信息的任何功能,这将是很糟糕的事。 Wi n N T提供者满足了这种要求。
另外,Wi n N T允许访问属于各个机器的一些信息,例如运行 N T服务。缺省情况下,这些信息并不存储在以域为中心的 A D里。
21.6 ADSI的适用范围图 2 1 - 7表示了一个客户程序 (典型的 A S P页面 )用 A D S I访问目录时,各种各样的软件联系在一起的方式。
图 21-7 客户程序与目录和其他软件之间的联系图 2 1 - 7表明 A D S I介于目录和客户程序之间。可把它想像成一套能翻译客户所使用的 A P I
的组件,这些 A P I用于对目录的访问。 A D S I是标准的基于 C O M的 A P I,A D S I是客户程序唯一需要了解的 A P I。从这种程度上,A D S I和 A D O的工作方式相差不多。
注意图 2 1 - 7中标出了客户程序通过网络的可能点,即实线与虚线相交的点。 A D S I提供者是进程内的组件,因此被放在运行 A S P页面的机器上。另一方面,目录服务程序可能被放在另一台机器上。在 I I S里,因为是在 I I S下运行 A S P页面,所以 I I S肯定在 A S P页所在的同一台机器上!然而当在 V B或 C + +里用 A D S I时不一定是这样,这也是为什么在网络中列出了 I I S元数据库的原因。
A D S I,和 A D O一样,使用了一系列的提供者。一个 A D S I提供者是一个能访问目录集或某个特定目录的 C O M组件集。安装 A D S I时,会发现它附带一些 M i c r o s o f t写的标准提供者 (称
624计计 ASP 3 高级编程 下载网络:机器间的边界网络:机器间的边界
ASP 页面
(客户)
ADSI LDAP
提供者
LDAP
协议活动目录目录其他 LDAP
目录关于网络中计算机的信息元数据库
ADSI WinNT
提供者
ADSI IIS
提供者为系统提供者 )。所能得到的提供者某种程度上依赖于所安装的软件,它们一般包括:
LDAP提供者:能访问任何符合 L D A P标准的目录。
Wi n N T提供者:能访问 N T 4控制的域中的机器上的信息。
IIS 提供者:能访问 I I S元数据库。
NWCompat和 N D S提供者:能访问 N o v e l l目录。
你可能已注意到这正好与前面所看到的常见目录的列表相对应。
请注意,尽管这些提供者被不同的组件实现,但它们一般提供相同的接口。
本章将主要讨论 L D A P和 Wi n N T提供者。用 Wi n N T提供者来浏览它显示出来的目录,用
L D A P提供者浏览 A D。
注意没有单独的,A D提供者”,因为 A D完全符合 L D A P兼容标准,L D A P提供者完全能满足需要。这也是为什么 A D里所有的 A D s P a t h s都以,L D A P:,开头的原因。
21.7 LDAP的适用范围前面已经说明,L D A P是一个访问目录的标准协议。从这方面讲与 A D S I很相像,这可能会让人感到奇怪:为什么有两个标准,为什么图 2 1 - 7中先通过 A D S I,再通过 L D A P来访问 A D
和其他 L D A P目录。
L D A P不是一个 M i c r o s o f t标准,是一个被承认了的工业标准。它不是为脚本语言而设计的标准,相反被设计成能够提供一种普通的传输方式,使得在目录里的查询等操作能沿网络传输。如果读一下 L D A P自身的规范 (RFC 2252),将会发现它充满了信息格式等内容。其辅助规范 ( R F C 2 2 5 3 ~ 2 2 5 6 ),更是包含了几乎只与高级程序员有关的内容,如 L D A P使用的 CN =
w h a t e v e r格式 (称为区别名,distinguished name)的定义。
R F C是 I n t e r n e t上建议使用的定义协议的文档。最终在给定的 R F C里提出的建议将被正式做为一个标准接受,这种情况下 R F C提供了协议的最后定义,上面提到的与 L D A P相关的 R F C 就是这样。可在下面网址找到 R F C的列表,h t t p,/ / w w w.
i e t f,o rg / r f c /。
L D A P确实引入了一个 A P I,这是一套 C语言风格的函数。如果用 C或 C + +编程,这当然很好,如果用 A S P编程,它恐怕不太好使用。
相比之下,A D S I是 M i c r o s o f t定义的,并不是工业标准。 A D S I的定义着重在最终客户端可
“看到”的接口。对于我们,客户是 A S P页面,尽管客户程序也可用 C + +,V B和其它众所周知的语言编程,但现在关注的是 A S P页面的情况。 A D S I的定义里没有任何关于怎样与目录服务通信的内容,也没有任何关于网络信息传输协议的内容。从这个意义上,A D S I有时被看作客户端的 A P I;它用来定义客户程序使用的 A P I。客户程序需要关心的只是能有一个 A D S I提供者与需要的目录通信,而这个提供者如何与目录通信是实现的细节,这与客户程序无关。
从这段说明不难看出 A D S I和 L D A P是怎样结合在一起的。一方面,有了用于客户端脚本程序的容易使用的 A P I的规范,另一方面,有了用于在网络上与目录服务通信的优良协议。如果能编写一个使用这个协议的 A D S I提供者,则就拥有了脚本程序用来访问响应这一协议的任何目录服务的提供者。这就是所谓的 ADSI LDAP提供者。可以将其想像成在 L D A P和 A D S I之间转换的组件。可用 ADSI LDAP提供者来访问任何遵循 L D A P标准的目录,包括 A D、
第 2 1章 A D S I和 A D介绍 计计 625下载
Exchange Server目录和 N e t s c a p e目录服务器。这就是为什么图 2 1 - 7中有几个目录可以通过
A D S I和 L D A P链进行访问的原因。
21.8 绑定到一个 A D S I对象在这一节中将开始编一些程序。首先,使用 Wi n N T提供者,然后与 A D进行比较。因为这能确保即使在 NT 4.0环境下这些程序仍能运行,还因为 Wi n N T毕竟有更简单的目录结构,使得对 A D S I的介绍大大简化。等到有更多的编程经验时,再回到 A D。
用 V B S c r i p t绑定到一个 A D S I对象很简单,只需向 V B S c r i p t里的 G e t O b j e c t方法提供对象的
A D s P a t h,如下所示:
运行了这一句后,o b j D o m a i n将拥有一个 ADSI COM组件的引用,通过使用 A d s P a t h
,Wi n N T,/ / To p O f T h e P o p s”访问这个对象。因为现在运行的是 NT 4.0中的 To p O f T h e P o p s域,
这个对象由 Wi n N T提供者提供,代表我们的域。
不论使用什么样的提供者,绑定到一个对象都是这样的步骤。例如,如果想用 A D来看一下自己的用户帐号,可以这样:
在其他的例子里,直接使用了 A D s P a t h,这是因为我们对它及其结构非常熟悉。
如果不能确定一个 A D s P a t h,一个好办法是利用 a d s v w,e x e来浏览一下整个目录。稍后,讲到查找时,将不需要提供 A D s P a t h来定位对象,查找操作将找到它们。
注意到使用不同的提供者是多么容易了吗?不需要像在 A D O里那样为设定一个连接字符串而烦恼。每个对象的 A D s P a t h都是以提供者的名字打头,紧接着是,,/ /”,因此 G e t o b j e c t仅根据 A D s P a t h就能知道需要哪个提供者。当提供了正确的 A D s P a t h时将得到指向正确组件的引用。
A D s P a t h里,,/ /”后的具体格式决定于具体的提供者,从前面的例子中会发现 Wi n N T以
,/”分隔组件,而 L D A P以“,” (逗号 )分隔。还有,从左至右,Wi n N T是下行目录,而 L D A P
是上溯目录。还可看出开头的 Wi n N T或 L D A P是大小写敏感的,但后面的字符串则不敏感。
21.8.1 ADSI对象和 D i r e c t o r y对象前面已经强调过不要把 C O M对象和目录对象混淆,然而可能会发现 G e t O b j e c t给出的总是对 C O M对象的引用。这怎么办? A D S I做得很聪明。你得到一个 C O M对象 (即一个组件 )的引用。
这组件存在于本地的机器上,甚至是进程内的组件,除非由 C O M +进入运行用户的 A S P页中的。
这组件不是目录里的对象,但它装作是目录里的对象,可说它是目录里的对象的代理。尽管有些情况下需要注意到他们之间的区别,但就一般应用程序而言,可把它看成目录对象自身。
所以在说明了要注意 C O M对象和目录对象之间的区别之后,在编写 A S P页时,可把它们当做同一回事。以下就是这样做的。
然而,仍需意识到这种区别,以便知道程序代码到底是怎样执行的,但在大多时间它并
626计计 ASP 3 高级编程 下载不影响编写的代码。稍后,我们将指出在哪几种情况下这种区别很重要。
类似地,还将研究目录对象属性与组件的自动化属性的不同。当开始编程时你会发现在这方面区别更明显,但很多时间将会发现 A D S I里组件的自动化属性就像真实目录属性一样。
由于 Wi n N T提供者装作它正在访问一个正确的目录,这里有很多伪装的操作!但这些都是有益的,这些使 Win NT成为一个易用的 A P I。
21.8.2 查看 A D S I对象的属性下面将把上面的小代码段扩展成为一个与 Wi n N T里的域对象绑定的 A S P页页,并且显示此对象的一些基本信息。这页面称为 D o m a i n I n f o,a s p,运行结果如图 2 1 - 8所示。
图 21-8 运行 D o m a i n I n f o,a s p时的窗口以下是产生图 2 1 - 8屏幕的代码:
第 2 1章 A D S I和 A D介绍 计计 627下载我已使这个页面尽量简单,因为这是本章的第一个 A D S I例子,所以它甚至不包含任何错误检查。 On Error Resume Next确保在发生错误时程序忽略错误而继续前进,如果显示一个属性时出现问题,则程序继续显示其他属性而不去查找错误的原因。
你理解这段代码应该不会有什么困难。它绑定了刚才描述的 A D S I对象,然后列出了一些自动化属性的值。这些属性有:对象的名字,A D s P a t h类、模式以及父对象的 A D s P a t h。模式可能是唯一新的属性。它包含了类模式对象的 A D s P a t h,而类模式对象包含了这个对象的必选和可选的属性。名字在 A D里指的是普通名 ( C N )。一般来讲,C N是 L D A P的术语,A D S I则用 N a m e。
在幕后我们实际上使用了一个名叫 I A D s的接口。所有的 A D S I目录对象都提供这个接口,
它提供了很多给出对象的基本必需信息的自动化属性以及一些得到和设置模式里定义的目录对象的属性的方法。
尽管还没有使用 I A D s提供的任何方法,但刚才几乎演示了它所有的属性。 (有一个例外—
G u i d它给出了一个唯一的 G U I D,它依赖于目录,指出对象的类或某个实例,但本章不会用到 G u i d )。尽管还没有碰到过 I A D s的方法,为了方便仍将把它们全列出来。在没有进一步讲一些概念之前,你可能对这些方法的解释不理解,请暂时将这张表作为参考。 I A D s属性如表
2 1 - 2所示。
表 21-2 IADs的属性及说明属 性 说 明
N a m e 存储对象的名字,对于 L D A P提供者,这通常与 L D A P普通名一样
A D s P a t h 存储对象的 A D s P a t h
C l a s s 存储对象的类
S c h e m a 存储描述这个实例对象所属类的类模式对象的 A D s P a t h
P a r e n t 存储包含这对象的对象的 A D s P a t h
G u i d 存储一个能唯一确定这个对象的 G U I D,这个属性不总是被实现注意所有的 I A D s属性都是只读的。
I A D s方法如表 2 1 - 3所示。
表 21-3 IADs方法的参数及说明方 法 说 明
G e t 检索模式里定义的一个属性的值
G e t E x 与 G e t类似,但返回值的格式不同
P u t 设置模式里定义的一个属性的值
P u t E x 与 P u t类似,但包含与多值的属性相对应的更多的选项
G e t I n f o 从目录服务发送数据更新高速缓存
S e t I n f o 从高速缓存取数据更新目录服务
G e t I n f o E x 与 G e t I n f o类似,但通过只拷贝某些指定的属性来实现对网络调用的优化在处理 A D S I时你会逐渐熟悉这些方法,因为它们是获得和设置目录对象的信息的基础。
因此,所有代表目录对象的组件上必须有提供这些方法的接口。
21.9 浏览目录:枚举容器的所有子对象通过上一节论述得知绑定一个目录对象是非常简单的,尽管实际上绑定的是包装该目录
628计计 ASP 3 高级编程 下载对象的组件,但 A D S I使这看起来几乎是一回事。在这一节中,将说明列出一个对象所有的子对象也是非常容易的。
下面用另一个例子来实现,称为 U s e r B r o w s e,a s p。这个 A S P页面例子用 Wi n N T提供者列出了域里所有的用户帐号。域里所有的用户帐号都是域对象的子对象。所以真正需要做的是绑定到域对象,然后列出它所有的子对象,这恰好就是 U s e r类。
以下是代码:
运行结果如图 2 1 - 9所示。
观察一下代码,显示用户对象的名字和 A D s P a t h采用的是通常方式。有趣的一点是如何枚举他们:
第 2 1章 A D S I和 A D介绍 计计 629下载图 21-9 运行 U s e r B r o w s e,a s p时的屏幕界面这段代码表示,对象 (这里是容器 )同 C O M集合一样被实现,所以能用一个 F o r.,,E a c h循环枚举它们的子对象。
开始循环以前,首先设置域对象的 F i l t e r属性的值。这个属性包含了一个字符串数组,其作用是指定需要列出的目录对象的类。在 Wi n N T目录里,域对象包含的不仅有用户帐号,还有域中的工作组和计算机帐号。现在不需要其它对象,因程序仅对用户 ( U s e r )感兴趣,所以程序设置了过滤器以指明这一点。如果这参数是空的,那么将返回所有的子节点。
或许你已经注意到了 F i l t e r并不是 I A D s定义的属性。很明显域对象必须提供另一个接口。
这里所使用的接口称为 I A D s C o n t a i n e r,所有是容器的目录对象都实现它。为了便于参数,表
2 1 - 4和表 2 1 - 5中列出了 I A D s C o n t a i n e r所有的属性和方法。
表 21-4 IADsContainer的属性及说明属 性 说 明
F i l t e r 指出需要列出的子对象的类
H i n t s 与 F i l t e r相似,但它指定的是不返回的对象的类,它限制了属性从子对象里拷贝,因此可最大限度地减少网络访问
C o u n t 符合 F i l t e r条件的子对象的数目。注意这个属性并不总是被实现。例如,目前 Wi n N T
提供者就还没有实现它从表 2 1 - 5中可以看出,在目录里移动和创建对象时,I A D s C o n t a i n e r正是所需要的接口。
一般而言,通过在被操作的对象的父对象中调用 I A D s C o n t a i n e r的方法执行这一类操作。因为只准备用一章讲 A D S I,所以将不探讨怎样增加和移动目录项。
630计计 ASP 3 高级编程 下载表 21-5 IADsContainer的方法及说明方 法 说 明
M o v e H e r e 将一个目录对象从别的地方移动来作为本对象的一个子对象。可用这个方法来移动或重命名对象
C o p y H e r e 与 M o v e H e r e类似,但它是将指定的对象拷贝一份
D e l e t e 从目录中将本容器的一个子对象删除掉
C r e a t e 按参数中指定的名字和类创建本对象的一个子对象
G e t O b j e c t 与 V B的 G e t O b j e c t类似,但只能获得对本容器的子对象的引用,所以使用时不需要指定完整的 A D s P a t h,而只需要指定对象的名字即可当然,I A D s C o n t a i n e r的方法不是由 I A D s接口提供的这一事实对 A S P代码来说是完全透明的。无论如何,代码是通过 I D i s p a t c h调用方法,所以不需要意识到现在正面对着两个不同的接口。
注意,如果要在目录中上行而不是下行,事情有点复杂。需要对象的 P a r e n t属性,但是因为仅给出了对象的 A D s P a t h而不是对它的引用,所以还需要单独用 A D s P a t h来绑定对象,如下面代码:
I A D s和 I A D s C o n t a i n e r是关键的接口。另外还有很多 A D S I接口,但它们一般是由特定类型的对象提供的特殊接口,与初学者无关。
21.10 使用模式定义的属性前面已经使用了 I A D s的自动化属性了解了对象的基本信息。但对象很可能还有更多的在模式里定义的属性。一般说来,不能像访问自动化属性那样访问它们,因为如果这样的话,那就意味着任何设计相关
C O M接口的人都能预言模式将定义什么。
这显然不可能,因为如果要在目录打开后进行维护,A D S I接口必须用于一般目录而不是某些特定的目录。 I A D s有一些将属性名作为参数以获取或设置属性值的方法。这些方法是 G e t,G e t E x,P u t和
P u t E x。这种方式额外的一个优点就是,
可以不用事先知道属性的名字就能列举一个目录对象的所有属性。
下面的 A S P页就是这样做的。这种情况下,它绑定到 Wi n N T里一个包含用户帐号细节的对象,并且使用模式遍历所有的可选和必有的属性,如图 2 1 - 1 0所示。
注意到有些属性没有值。这也许是第 2 1章 A D S I和 A D介绍 计计 631下载图 21-10 ADSI属性浏览屏幕界面因为这些属性值是用 A N S I字符集无法显示的数据类型 (这种情况下相关 R e s p o n s e,Wr i t e的语句会出错 ),也许它们是可选属性,碰巧没有设置相应的值。图 2 1 - 1 0也说明了 Wi n N T里的用户对象没有任何必有属性,因为,Mandatory Properties”表里没有任何项。
下面是 A S P代码:
632计计 ASP 3 高级编程 下载对于这些代码还需增加一些新的代码。首先,以一般方式绑定用户对象,在这种情况下,
需要增加一些错误检查。
现在枚举所有的可选和必有的属性。因为需要类模式对象,所以绑定类模式对象:
现在显示类模式对象的 A D s P a t h,这一步并不是必不可少的,需要强调一下这个对象只是一个普通对象,可像对待其他目录对象一样对待它,而且对其访问也只是使用了极为普通的
A D S I组件。
如果安装了 a d s v w,e x e,那么可以用它向下浏览目录并找到 Wi n N T模式对象。你将在
,Wi n N T,/ / < D o m a i n N a m e > / S c h e m a”的容器里找到它们。
接下来的步骤使用了类模式对象的一对新的自动化属性,M a n d a t o r y P r o p e r t i e s和
O p t i o n a l P r o p e r t i e s。这两个属性包含了列有可选和必有属性名称的数组。它们由另一个现在还没有讲过的接口 ( I A D s C l a s s )实现,I A D s C l a s s接口由模式对象提供。
因为数组里的每一个字符串是一个必有属性的名字,所以能使用下面的代码显示它们的名字和值,这段代码是从上面的 P r o p e r t y B r o w s e r页简化得到的:
类似地,可用 O p t i o n a l P r o p e r t i e s数组列出所有的可选属性。
你可能会奇怪为什么使用名为 M a n d a t o r y P r o p e r t i e s和 O p t i o n a l P r o p e r t i e s的自动化属性,因为先前提到 A D有名为 m u s t C o n t a i n和 m a y C o n t a i n的属性。事实上在 A D里用它们当中的任何一对都有效 (但在 Wi n N T里不是 ),但是用 m u s t C o n t a i n和 m a y C o n t a i n时它需要用 G e t方法,因为那些名字的没有自动化属性,因此使用:
这实际是不同标准之间存在的问题。 L D A P使用 m u s t C o n t a i n和 m a y C o n t a i n。而 A D S I使用
M a n d a t o r y P r o p e r t i e s和 O p t i o n a l P r o p e r t i e s。因为本书正在用 A D S I的 A P I,所以下面还是统一用第 2 1章 A D S I和 A D介绍 计计 633下载
A D S I的方式比较好一些。
2 1,11 Get和 G e t E x
尽管例子 P r o p e r t y B r o w s e,a s p看起来像是要列出所有的属性,但却有一个较大的缺陷:仅对单值的属性有效,而不能显示多值的属性。问题是下面代码的第五行引起的:
这行程序假想 G e t方法返回的变量都是可打印的。但实际上有许多理由证明情况不总是如此。事实上,G e t返回一个 Va r i a n t,它的值是否可打印决定于 Va r i a n t里包含的数据的类型。这属性可能根本不包含任何值 (返回一个空 Va r i a n t,或者该值可能是某种二进制格式的。还有,
一些属性返回对其他对象的引用,例如 A D里的对象的 n T S e c u r i t y D e s c r i p t o r属性就这样,这已超出了本章讨论的范围。
然而,属性内容不能打印的原因之一是属性可能是多值的,在这种情况下 G e t将返回包含一个数组的 Va r i a n t。
多值属性的存在使 I A D s提供了两个返回属性值的方法 G e t和 G e t E x。它们的区别是:如果只有一个属性值则 G e t将其作为 Va r i a n t返回,如果有多个属性值则 G e t返回的 Va r i a n t包含一个属性值的数组。而 G e r E x返回的 Va r i a n t总是包含一个属性值的数组。如果属性只有一个值,则这个数组将只有一个元素。
很明显,到底用哪一个取决于编程人员的喜好和在具体情况下哪一个更方便。通常,如果不知道一个属性是单值还是多值的,很可能用 G e t E x,因为用 G e t则不知道它的返回值的格式。在 P r o p e r t y B r o w s e,a s p页里选择用 G e t是因为已经知道 Wi n N T的用户对象里没有多值属性。
但如果希望这个页具有更一般的用途,确实需要它能够列出多值的属性。这也是下一个示例所要完成的任务。
要指出的最后一点是,你会发现有些情况下用 G e t或 G e t E x方法能够获得属性,也可以作为自动化属性获得属性。在 A D S I的设计者预料到某些属性会被某些对象经常使用,并因此增加接口提供这些属性做为自动化属性时,会发生上述情况。例如对于 Wi n N T里的用户对象,
以下两行代码效果是一样的:
和:
A D S I的 M S D N文档包含了关于不同的提供者可能提供的属性的详尽细节。
21.12 PropertyBrowseEx示例这个例子与 P r o p e r t y B r o w s e例子相似,但有两个不同点:第一,使用了 G e t E x而不是 G e t,
因此列出了所有的多值属性,并用同样的代码列出了单值属性。第二,对想要查看的对象的
A d s P a t h,它使用了一个 H T M L窗体,允许用户填入 A d s P a t h,而不是在程序中硬编码。这使
634计计 ASP 3 高级编程 下载得能用同一个页面来查看不同的对象和不同目录里的对象。
图 2 1 - 11就是运行时的页面。
如果键入一个对象的 A D s P a t h并点 S u b m i t,将得到与 P r o p e r t y B r o w s e例子非常相似的输出。
图 2 1 - 1 2里查看了作者的域控制器 B i g g y B i g g y的文件服务。这文件服务是负责对来自网络中其他计算机要访问本机的共享文件和文件夹的请求 进 行 应 答 的 N T 服 务 。 它 的 名 字 是
l a n m a n s e r v e r。
这里的程序代码与 P r o p e r t y B r o w s e例子非常 相 似 。 注 意 在 窗 体 中 的 代 码 以 选 定 的
A D s P a t h作为默认值,这样对用户更友好。
第 2 1章 A D S I和 A D介绍 计计 635下载图 2 1 - 11 Property BrowseEx屏幕 1
图 21-12 PropertyBrowseEx屏幕 2
21.13 AD与 Wi n N T提供者比较
A D和 Wi n N T提供者之间有很多的重叠,二者在某种程度上都提供了对相同信息的访问。
636计计 ASP 3 高级编程 下载通过二者中的任意一个显示出的信息都包括域中全局用户、工作组和计算机帐号。除此之外,
Wi n N T提供者还允许获得成员计算机上的 N T本地服务和打印任务的信息。另一方面,A D允许了解域林 (domain forest)的配置信息和系统管理员选择存在那里的任何其他数据。
分别用 Wi n N T和 L D A P提供者查看数据,可看到 Wi n N T和 A D之间更多的不同点。在图 2 1 -
1 3和图 2 1 - 1 4的屏幕截图中用 P r o p e r t y B r o w s e E x,a s p查看用户帐号,分别使用二者的提供者。
图 2 1 - 1 3是 Wi n N T版的用户帐号对象。
图 21-13 Wi n N T的扩展属性浏览窗口图 2 1 - 1 4是同一个用户帐号作为 A D里的一个对象被查看时的屏幕。
A D的屏幕截图里更小的滚动条滑块表明了 A D能为它的对象存储比 Wi n N T更多的属性。
另一方面,大多数可选属性的值是空的,这仅仅是为了万一系统管理员需要使用他们存储信息而定义的。还有,Wi n N T没有必有属性,而 A D有几个,包括前面讨论过的 o b j e c t C l a s s。
o b j e c t C l a s s显示了用户类继承树里所有的类 o b j e c t C a t e g o r y是将在学习如何执行查找时遇到的一个属性。它携带了与 o b j e c t C l a s s类似的信息,但对查找更有效。 s A M A c c o u n t N a m e是用来注册的名字,而且它对应于 Wi n N T提供者里对象的 N a m e。 n T S e c u r i t y D e s c r i p t o r和 o b j e c t S i d包含了对象的安全信息。二者都不能显示,因为 n T S e c u r i t y D e s c r i p t o r实际上是对一个安全描述符第 2 1章 A D S I和 A D介绍 计计 637下载组件的引用,而 o b j e c t S i d是二进制格式的。
通常认为,Wi n N T提供者是一个基本的提供者,只显示了其对象的最基本信息。例如,
它不提供对安全描述符的访问。如果想用最短的代码做一些最简单的事情,则 Wi n N T更易用。
A D里更多的信息是有代价的,要想学会它更困难。如果网络处在一个 NT 4.0主域控制器管理下,那么将因无法访问 A D而不得不使用 Wi n N T提供者。另一方面,用 Wi n N T提供者是无法查找的,所以如果要写一个需要完善的查找机制的 A S P页,就必须选择 A D。
图 21-14 AD的扩展属性浏览窗口
21.14 属性缓存因为目录服务程序可能运行在网络的任何地方,所以访问任何一个属性可能是一个很慢的过程。为了将这个问题的影响减少到最小,每一个 A D S I的组件保留了相应目录对象的一些或所有属性的一个本地拷贝。这个本地拷贝称为属性缓存。因把所有属性从目录拷到属性缓存而使网络阻塞问题减到最少,客户程序可从缓存里取用它想要访问的属性。如果改变了一些属性,那么可以调用一个方法 ( I A D s,,S e t I n f o )把整个缓存写回目录,即更新目录。有一个独立的缓存确实意味着缓存或目录本身都可能有属性的一些陈旧的值,但前面已经说了,对于
638计计 ASP 3 高级编程 下载目录来说这不是一个很严重的问题。客户端程序可在任何时候选择从目录到缓存或从缓存到目录更新数据。
分析一下前面的 I A D s方法的列表,会发现有三个处理这种更新的方法。 G e t I n f o,S e t I n f o
和 G e t I n f o E x。 G e t I n f o根据目录更新整个缓存,而 S e t I n f o则相反。如果仅需要个别的属性,可用 G e t I n f o E x代替 G e t I n f o。
一般而言,修改了属性的值后必须调用 S e t I n f o。你可能以为每次查看属性前总是要调用
G e t I n f o,但实际上不必要。在缓存里,当第一次试图访问一个属性时,组件将检查缓存有没有被预置,如果没有,将隐式地调用 G e t I n f o。只有怀疑拥有的值是陈旧的而想更新时,才需要显式地调用 G e t I n f o。
I A D S的 G e t,G e t E x,P u t和 P u t E x方法,以及自动化属性,只处理属性缓存,而不是目录。
所以,如果要调用 G e t来查看一个属性的值,将只能得到缓存里的值,但当属性缓存没有被初始化时,隐式地调用 G e t I n f o。
属性缓存的处理是需要意识到所使用的 C O M组件与最终想要处理的目录对象之间的区别的一个领域。
21.15 设置属性的值目前讨论的例子都是关于如何读属性的信息,但写入新值也很容易。对于一个单值的属性,仅需要用 I A D S,,P u t方法。例如,如果想改变一个用户帐号的描述,可用以下代码实现:
注意对 S e t I n f o的调用。可以在改变了本地缓存后立即调用它,但如果做完所有的改变以后再这样做效率会更高一些,这样只需要调用一次。
如果要设置一个多值属性,用 P u t E x会比用 P u t更好一些。区别是对于一个多值的属性,
修改数据有几个不同的途径。可能想在当前值里增加一个新值,或替代当前所有的值,或删除一个或几个值。同样,对于可选属性,可能想清除它的所有值。 P u t E x与 P u t作用差不多,
但它有一个附加的参数来指明如何做这些改变。所有的细节都在 A D S I的文档里,在这里就不深入讨论了。
21.16 目录的验证迄今为止,我们举了很多例子了,但一直是假定有足够的安全权限来执行它们。但是,
这一点存在着问题。我们正在处理 A S P页,这意味着页面很可能要运行在互联网客人帐号下。
假设系统管理员的业务非常好,那么互联网客人帐号几乎不可能改变由遵从 A D S I的目录提供的任何数据。它甚至也不允许查看目录里太多的数据,如果试着运行前面的任何一个例子,
就可能会发现迄今为止之所以能侥幸运行成功,仅仅是因为这些例子没有试图修改或浏览一个特别敏感的数据。
所以必须讨论怎样提供更多适当的安全证书的问题。
下一个例子就这样做了。这是一个很简单的例子,它所做的只不过是验证是否提供了适第 2 1章 A D S I和 A D介绍 计计 639下载当的用户名和口令。为了简单起见,所有诸如机器名等信息都硬编码在代码中,如同前面的一些例子,如果从其他站点下载,那么在运行前需要改变一些名字。
这个页面看起来很简单,仅仅说明了它起的作用,运行的屏幕图如图 2 1 - 1 5所示。
关键的是这几行:
从这里可以看出验证分两步。第一,用 G e t O b j e c t绑定到目录顶端的对象,即其 A D s P a t h
为提供者名加上冒号的对象,也就是 Wi n N T:或 L D A P:或 I I S,。这个对象称为名称空间对象。
640计计 ASP 3 高级编程 下载图 21-15 ADSI目录验证屏幕然后可以调用名称空间对象提供的一个方法 O p e n D S O b j e c t,来真正返回对所需要的对象的一个引用。 O p e n D S O b j e c t实际上是通过接口 I A D s O p e n D S O b j e c t实现的,而 I A D s O p e n D S O b j e c t
只能由名称空间对象提供。它需要四个参数:所需的对象的 A D s P a t h,想绑定到帐号的用户名和口令,以及一个包含了各式各样的关于验证实现的标志位的整数值,通常设置为 1,并需要基本的普通 Wi n N T / Windows 2000验证。
尽管这个过程看起来并不复杂,但是必须意识到这只不过是因为提供者为验证所做的工作已经被很好地隐藏了。提供者可能需要在幕后模拟另一个用户,或者它可能需要创建一个新的连接。在这里有很多的原因,大部分与安全性有关,为什么会出错,有一些原因在知识库的 2 1 8 4 9 7和 1 5 8 2 2 9文档里讨论了。因此,可能宁愿用
I I S本身的基本验证或 N T L M验证来提供适当的安全证书,而不去依赖 O p e n D S O b j e c t
方法。这也是在本节没有花很多时间讨论 A D S I验证的原因。
21.17 查找这是在本章所要讨论的最后一个题目,它是 A D S I里的最重要的内容之一。如前面所提到的,目录的最重要的方面之一就是它支持复杂的查找。迄今为止,已讲过的所有例子都是依赖于已经知道要绑定到的对象的 A D s P a t h。查找可以避免这个因素。通过某种方式表明“不知道这个对象在目录里的位置,但知道关于它的属性的一些内容”,例如可能是一个名叫
,H e n r y”的用户帐号。
事实上,尽管应用程序查找时将间接使用 A D S I,但是使用 A D S I的事实却被很好地隐藏在幕后。这是因为查找通过 A D S I访问目录的方式实际上根本不直接使用 A D S I,而是调用一些
A D O对象来代替。这些 A D O对象将在内部使用 A D S I提供者的服务。
这样做的理由是因为脚本语言的一个限制。目前,脚本语言只能通过使用 I D i s p a t c h接口同 C O M组件通信,不能直接调用其他接口的方法。这还不是个大的问题,因为所需的所有
A D S I接口都是双重的接口。但是,A D S I用来实现查找的接口叫作 I D i r e c t o r y S e a r c h,它是一个定制的接口,不能被脚本客户直接使用。
以上情况与 A D O和 OLE DB的情况很相似。当使用 A D O时,真正访问数据源的不是 A D O
组件,而是 OLE DB组件。 A D O组件存在的唯一理由是代表程序调用 OLE DB组件,这样就能解决 OLE DB不是为脚本语言设计的问题,而且这样也能使用定制的接口。现在需要做的另外一步是,A S P页必须访问一个 A D O组件的服务。这个 A D O组件进而访问一个 OLE DB组件,
最后 OLE DB组件用一个用于 A D S I的 OLE DB 提供者来调用 A D S I接口里的方法,来访问目录
(在 A D O看来,目录是数据源 )。这个过程如图 2 1 - 1 6所示。
图 21-16 查找目录的过程示意图第 2 1章 A D S I和 A D介绍 计计 641下载客户 ADO OLE DB
目录服务用于 ADSI的
OLE DB提供者图 2 1 - 1 6看起来复杂,但是其客户代码很简单。
在查找时还有一件事情必须意识到。尽管查找在目录里有普遍的重要性,但并不是所有的 A D S I提供者都支持它。 WinNT ADSI 提供者就不支持,不能用这个提供者来进行查找。这是取决于其工作的机制,Wi n N T搜集整个网络的信息,所以在它后面根本没有真正的拥有支持有效查找的基础设施的后端目录。
ADSI LDAP提供者允许查找,并且任何符合 L D A P标准的目录也必须这样,因为查找是
L D A P规范所要求的。因此可以对 A D实施查找,所以最后一个例子将是基于 A D的。
以下的例子演示了这一点。这个例子名为 S e a r c h,a s p,使用 L D A P提供者来实现一个查找。
为简单起见,所有的查找参数已经硬编码在页面中了,它们请求了对目录中所有用户的查找。
图 2 1 - 1 7所示为页面运行情况。
图 21-17 运行 Search.asp 时的屏幕图 2 1 - 1 7 所示 屏 幕 截图 表 明 已经 找 到 了所 有 的 用户,并 列出 了 每 一个 用 户的
s A M A c c o u n t N a m e和 A D s P a t h。紧靠表上方的命令文本是传送到 A D O的产生这个结果的命令。
在看了产生这个屏幕的代码后,将看一下这个文本所需要的语法。现在,你可能注意到命令文本是由页上端的四个字符串组成的:查找基 (search base)、过滤器 ( f i l t e r )、所需属性
(properties requested)和范围 ( s c o p e )。
查找示例的代码是这样的:
642计计 ASP 3 高级编程 下载这里不需要做过多的解释,因为它大部分是标准的 A D O信息,这些在本书的前面已经讲过。我们建立了一个命令并传送一个字符串给命令对象的 E x c u t e方法。注意这里根本没有直第 2 1章 A D S I和 A D介绍 计计 643下载接创建任何 A D S I对象!所谓的新内容就是要传给 A D O连接对象一个字符串以表明要使用用于
A D S I的 OLE DB提供者 ( A D s D S O O b j e c t ),以及命令字符串是如何组织的。
21.17.1 用以查找 A D S I目录的命令字符串回顾一下用来请求查找所有用户的字符串。为了提醒,重新列出如下:
这个字符串由四部分组成,以分号分隔。需要告诉目录服务:
要找什么 (换句话说,查找操作所返回的对象必须满足什么样的条件 )。
在目录的什么地方找。
如果找到了这些对象,对它们的什么属性感兴趣。
对于本例来说,找什么是“任何是用户的东西”;在目录的什么地方找是“任何地方”;对它们的什么属性感兴趣是,s A M A c c o u n t N a m e和 A D s P a t h” 。现在好了。剩下要做的就是怎样把这几条信息按正确的语法转换成目录服务程序所能理解的形式。
先讲一下需要的属性,因为这是最简单的一条。组织一个字符串,它由一个被逗号分隔开的属性名的列表组成,像这样:
下一步是“找什么” 。这本身是一个大的题目。我们将使用查找过滤器 (search filter)。怎样建立查找过滤器是一个很大的题目,所以在下一节将更详细地讨论它。对于本例这个特殊的请求,只需要是用户的所有对象。相应的查找过滤器是:
注意格式,它指明某一个属性必须有某一个值。所有的查找过滤器最后都归结为像这样的一系列条件。指定的属性是 o b j e c t C a t e g o r y,因为在 A D里它包含了对象的一般类型的信息,
所以它对于使用这一类过滤器来说是一个方便的属性。
最后需要指明目录的那一部分是想要查看的。对于本例,假定对用户所处的位置一无所知,所以要指定整个目录。对于其他的查找,也可能对目录的结构有一些了解,并因而对在哪里能找到对象有一个粗略的概念。很明显,所指出的查找范围越精确,查找的速度就越快。
查找通常用于目录的子树。这需要指定子树的两条信息:位于子树顶点的对象的 A D s P a t h
和从这对象向下要找多深。位于子树顶点的对象的 A D s P a t h是查找基,而向下查的深度称为查找范围。
查找基很好理解,因为它只是个 A D s P a t h而已。
查找范围是一个字符串,可以是以下三个值当中的一个:
subtree:如果查找范围是这个值,那么查找将搜索基以下的整个子树。
o n e l e v e l:如果查找范围是这个值,那么只搜索查找基的直接子对象。这与利用
I A D s C o n t a i n e r方法枚举一个容器的内容很类似,但这里能指定更复杂的查找过滤器。
b a s e:如果查找范围是这个值,那么只查找一个对象,就是这个查找基本身。这类查询将返回一个对象或者不返回任何对象,这取决于这个查找基是否满足查找过滤器。看起
644计计 ASP 3 高级编程 下载来没有什么必要实现一个以基作为范围的查找,但 L D A P规范中有一些技术上的理由说明它是有用的。
现在已经具有了足够的信息来看一下命令字符串是怎样组织的:
查找基是,LDAP://dc = To O f T h e P o p s,dc = Fame,dc = com。
这是 A D的根对象的 A d s P a t h。
查找过滤器是,(objectCategory = person)。
这告诉目录服务返回所有的用户对象:
所需属性是,s A M A c c o u n t N a m e,A D s P a t h。
查找范围应为整个子树,所以它的值是,s u b t r e e。
命令文本是由这四个子串按以下格式组织起来的:
<查找基>;查找过滤器;所需属性;查找范围注意查找基是用尖括号括起来的,而分隔字符串用的是分号。还要注意不要加多余的空格。如果加了任何多余的空格以使它更易读,那么,目录服务能否识别该命令字符串就要看运气了 (这取决于把空格加在哪里 )。所以强烈建议不要多加一个空格!
21.17.2 查找过滤器查找过滤器包括一系列的条件。每个条件说明某一个属性必须有某一个值,而且这些条件用逻辑运算符 A N D (与 ),O R (或 )和 N O T (非 )连接起来,若以符号表示分别为,&”,,|”和
,!” 。可以在任何属性值里使用通配符,*”,而且每个条件以及整个过滤器必须用圆括号括起来。
例如过滤器:
将返回所有 s A M A c c o u n t N a m e以 b开头的对象,而过滤器:
将返回所有 d e s c r i p t i o n属性的值包含,a n d”子字符串的所有对象。
注意字符串都没有用引号括起来。
语法里与通常情况不一样的是,运算符,&”和,|”是放在运算对象的前面而不是之间。
例如,如果想表示对所有的其 a A M A c c o u n t N a m e s以 s开头的用户感兴趣,可以这样写:
而如果想要的是 a A M A c c o u n t N a m e s以 s或 t开头的用户,那么将这样书写:
括号保证了或 ( | )条件被先计算。
这语法与 L I S P和一些 H P计算机使用的逆波兰 (Reverse Polish)语法很像。
最后,有一个过滤器你将经常碰到:
这是检索所有对象的标准方式。它之所以生效是因为 (根据 L D A P规范 )所有的对象都必须有一个名叫 o b j e c t C l a s s的属性。这个过滤器说明了 o b j e c t C l a s s可以具有任何值。
这里说明了 L D A P查找过滤器的基础,用它们还可以干一些更高级的事情。欲了解详情,
第 2 1章 A D S I和 A D介绍 计计 645下载请查阅 RFC 2254,在那里,正式地定义了 L D A P查找过滤器的语法。
21.18 小结本章只介绍了 A D S I和 A D的最基础的内容,但凭这些内容已经可以开始用 A D S I来访问目录的内容。 A D S I是一个很强大的工具。用它可以改变口令、增加用户帐户、启动和终止 N T服务、处理打印队列以及管理 I I S自身,所有这一切都通过简单的脚本语言实现。很多这样的操作先前都是 Windows API函数的领域,需要用 C + +写的应用程序来实现。如果希望能够从一个
We b页里做这些事情,将需要用 C + +写一个能从 We b页里调用的组件,以实现所需操作。现在
A D S I出现了,能从 We b页里完成的任务 (尤其是管理任务 )的范围大大增加了。
646计计 ASP 3 高级编程 下载
D i r e c t o r y,A D ),以及怎样用 A S P访问目录服务和使用它们所包含的信息。这里的目录和目录服务实际上是指一种特定的数据库,该数据库能够有效地查找像网络资源目录一类的信息。
A D是一种网络资源的目录,而 A D S I是能够访问任何目录的 M i c r o s o f t技术。其他公司也有类似的技术,例如 S u n公司的 J N D I,但因本书是针对 Wi n d o w s的,所以在此只讨论 A D SI。
不要混淆 A D S I和 A D,它们是两种截然不同的技术。尽管如此,因为这两种技术确实是密切地相互作用,我们还是将它们放在同一章里讨论。 A D是随 Windows 2000诞生的大而新的目录,包含了所有的安全性和管理本地网域所需要的其他信息。另一方面,A D S I是一套
M i c r o s o f t作为访问任何目录的方法而推出的 C O M接口,这意味着 A D S I也是访问 A D的通常方法。尽管 A D只存在于 Windows 2000 Server和 Windows 2000 Advanced Server中,A D S I却适用于所有的 3 2位操作系统,Windows 2000 Professional,NT 4.0和 Windows 9x。
本章的目的是使读者掌握怎样用 A S P语言简单而又容易地访问目录,因此本章重点是
A D S I,但由于 A D的重要性,本章也将接触到 A D的一些相关功能。
本章只讨论了 A D S I的基础,如果想更深入地研究,请查阅,Professional ADSI
P r o g r a m m i n g》一书,Simon Robinson著,Wrox Press出版。
21.1 ADSI的用途这里有两个相关联的问题。前面讲过 A D O,在技术上 A D O符合 M i c r o s o f t的 U D A规范,本书第二部分里已深入讨论过。 A D O能访问任何有 OLE DB提供者的数据源。目录是另一种类型的数据源,为了使用目录,必须使用一种不同的技术 — A D S I。为了理解为什么要使用
A D S I,需要理解是什么使目录不同于一般的数据源,以及 A D S I能做哪些 A D O不能做的事。
A D O的确是一种通用的技术。原理上,M i c r o s o f t的目的是让 A D O可以访问任何数据源,
而不管这数据源的内部结构。但又在本质上重视关系型的数据源。这没有什么错,但这也确实意味着如果想访问分层结构的数据源,A D O可能不总是最有效的办法。因此引入 A D S I,因为 A D S I正是专门为分层结构数据源而设计的。精心设计的 A D S I使用户在浏览树状结构时感到比较容易,而 A D O就没这么轻松。
上面提到的分层结构的数据源和目录,它们是一回事么?它们相似,但不完全相同。下面先讨论相同点,即它们都是树状结构,再讨论目录区别于数据库和其他数据源的特征。
分层结构的数据源是按树状结构组织起来的,对象包含着其他对象,与 Wi n d o w s
的文件系统中的文件夹包含文件和文件夹一样,而多数目录也是这样的结构。
事实上,体会这一点最简单的方法是快速浏览 A D的结构。图 2 1 - 1是从 a d s v w,e x e中截取的,
a d s v w,e x e是一个通用目录浏览器,可用于任何基于 A D S I的目录 (包括 A D )。 a d s v w,e x e是由
ADSI SDK提供的。
图 21-1 A D的结构图 2 1 - 1中有很多我们将研究的内容,我们在后面再回来讲述,如果现在不能全看懂也不必担心。请注意左边的树状结构,它是一个标准的树控件,清楚地显示了 A D中数据的分层排列。以 CN = Simon Robinson为例,这是作者在局域网上的帐号,它的父级是 CN = Users。在目录用语里,父子关系称为包含关系。 CN = Users称为一个容器,包含了 CN = Simon
R o b i n s o n对象。在这个 A D中,CN = Users实际上包含了此域中所有的用户帐号,不过实际情况不总是这种。
同样,用户容器也被代表域的对象 DC = To p O f T h e P o p s包含着。 D C = To p O f T h e P o p s容易让人误解,因为域的全名是 DC = TopOfThePops,DC=Fame,DC=com,对应于一个虚拟的
U R L,To p O f T h e P o p s,F a m e,c o m ( Windows 2000支持这样的域名,而任何 NT 4.0机器只能识别第一部分 To p O f T h e P o p s )。不要为这些名字的格式而担心,这是 A D专用的,你很快就会适应,
C N代表普通名 (Common Name),而 D C代表域组件 (Domain Component)。
最后,树中的域节点被 L D A P对象包含。 L D A P代表轻量目录访问协议 ( L i g h t w e i g h t
Directory Access Protocol),这是一个访问目录的工业标准协议,该协议的引入表明了 A D是与
L D A P相联系的。后面将进一步讨论 L D A P。
迄今为止,所做的工作是指出我们正在存储大量的对象信息,并正在以分层方式管理这些信息。顺便提一下,这里所说的对象是通常意义下的,不是技术上的,在这里不指 C O M对象。 A D提供了一个非常好的例子,展示了 A D S I所能访问的目录的结构。下面将探索 A D的细节,并且演示目录的典型结构。然后,就可以学习如何用 A D S I去得到和修改目录中的信息。
但首先,来看一下如何获得所需的软件。
21.2 必需的软件在这一节中,由于 A D S I和 A D需要的软件不同,我们将分别讨论它们。
Windows 2000集成了 A D。如果你的计算机运行在 Windows 2000下,并将其作为域控制器,则已经安装了 A D,反之则不会。关键在于是否把 Windows 2000作为域控制器。如果在一个域内的 Windows 2000工作站,由一个 NT 4.0主域控制器控制,也不会有 A D。
616计计 ASP 3 高级编程 下载
A D S I也是 Windows 2000操作系统 ( P r o f e s s i o n a l或 S e r v e r )中的一部分,但能够从 M i c r o s o f t的 We b
站点上下载用于 NT 4.0和 Windows 9x的 A D S I。另外,可能需要 ADSI SDK来开发软件。无论正在用什么操作系统,都需要下载这个 S D K。它包含了各种各样的头文件和文档。尽管编写 A S P客户程序时,它不如用 V B或 C + +编程时那么必需,但它包含了图 2 1 - 1中使用的 a d s v w,e x e实用程序。
下面将使用 a d s v w,e x e进一步研究 A D。 a d s v w,e x e也叫做活动目录浏览器 (Active Directory
B r o w s e r ),这名字有些误导作用。这是一个通用的目录浏览器,可以检查任何 A D S I兼容的目录,而不只是 A D。活动目录浏览器是一个好工具,因为其本身使用 A D S I搜集信息,并显示给我们。因此,我们看到的信息的格式恰恰就是用 A D S I编程时所需要的。
正如前面提到的,a s d s v w,e x e是 ADSI SDK的一部分,可以从微软的 We b站点上下载。如果没有的话,我们建议下载一个拷贝,你会发现对于研究目录,它是非常有用的。
21.3 AD的内部结构
A D包含了一个域控制器管理一个域所需的全部信息。从这个意义上讲,它与 NT 4.0服务器中的域目录 (domain directory)是一样的。所不同的是它符合 L D A P标准。因为 L D A P是工业标准,所以很容易编写用标准 A P I函数 (包括 A D S I )来访问 A D的客户程序。相比之下,NT 4.0
上相应的数据库却是 M i c r o s o f t专用的,通过 Windows API函数只能得到少得可怜的信息。实际上,根本不能把该数据库用作集中管理网络资源的目录,但 A D可以。
另外,A D远比原有的 NT 4.0域目录强大。它连同 Windows 2000一起,支持下列概念:把域本身排列成域树 (domain tree),或允许很多独立的树共享配置数据,形成一个域林 ( d o m a i n
f o r e s t )。还允许把个人的信息像操作系统使用的资料一样存储进去。
就 A D中存储的信息而言,实际上有两个部分。缺省情况下,A D包含了管理一个域所需要的全部信息,如计算机、用户和工作组帐号,以及相应的安全权限。另一方面,A D被设计成通用的目录,这意味着任何其他系统管理员认为有用的内容都可存入 A D。所以像用户帐号这样的信息也可能出现在薪金明细和公司组织结构下面。 A D还有一套非常完善的安全系统,
由管理员分配细致的等级,决定谁具有对各式各样信息的读或写的权力。
但是,令我们最感兴趣的还是 A D的整体结构,我们将给出一个一般目录的例子。
21.3.1 目录里的对象和属性需要理解的第一件事情是:关系型数据库把数据存储在表的行和列里,而在目录里一个很重要的概念是对象,对象含有需要存放的信息。在图 2 1 - 1的屏幕截图中,我们就选了一个用户帐号的对象。 A D中的其他对象包括计算机、域和工作组等。稍后,当我们讨论 Wi n N T
A D S I提供者时将要碰到其他目录里的对象,如服务对象和打印队列对象等。
不要把目录中的对象与 C O M对象 (组件 )相混淆,目录里的对象与 C O M毫不相干。
它们有属性,但通常不具有方法。
实际上目录中通常除了对象没有别的,对象被排成层状。对象可被认为是由许多属性组成的。
注意在这里我们不是在讨论 C O M自动化属性,仅仅是在讨论一条条的信息。一个属性包括属性名和属性值。例如,上例中在 A D中的用户帐号的属性如表 2 1 - 1所示。
第 2 1章 A D S I和 A D介绍 计计 617下载表 21-1 示例对象的属性及其值属 性 名 属 性 值
C N Simon Robinson
A D s P a t h LDAP://CN=Simon Robinson,CN=Users,DC=TopOfThePops,DC=Fame,DC=com
s A M A c c o u n tNa m e s i m o n
D e s c r i p t i o n 一段注释,可用 a d s v w,e x e设置
M a i l s i m o n @ s i m o n r o b i s o n,c o m
以上这些属性大部分是不言而喻的。 C N代表普通名 (Common Name),是访问对象时的通常名字。 A D s P a t h是使用 A D S I访问目录时,可唯一确定该对象的名字,很像一个文件的完整路径名,包含了该对象本身和目录树中所有在其上面的对象的名字。 s A M A c c o u n t N a m e是用户在域中以这个帐号注册时的提供名字。
表 2 1 - 1展示的一个重要概念,就是一个属性有两个部分:名字 (如 C N )和值 (如 S i m o n
R o b i n s o n )。更准确地说是一个名字和一个或一个以上的值,因为有些属性是多值的。可把多值性想成一个值的数组。
顺便说一下,表 2 1 - 1只是属性中的一小部分,如果安装了 A D,在查看你自己的用户帐号时,
将发现数量巨大的属性。其中许多还没有值,只是为某些系统管理员偶尔的需要而准备的。
当使用 a d s v w,e x e时,可用屏幕右边的 Properties 列表框查看不同属性 (见图 2 1 - 1 )。
选中一个属性,它的值就在旁边的文本框中显示出来。如果想改变这个值,就在文本框中输入一个新值并单击列表框下面的 C h a n g e按钮。再点击 A p p l y按钮确认。
21.3.2 对象的类到目前为止,我们已使用 a d s v w,e x e查看了用户帐号的对象,别忘了还有其他类的对象,
例如专门针对计算机的对象。从这种意义上,一个用户和一个计算机 (对象 )的不同之处就是它们属性的数目和类型的不同。例如,选中图 2 1 - 2所示的这个对象。
图 21-2 计算机对象这是描述作者所在的域的域控制器的对象,这是一台名叫 B I G G Y B I G G Y的计算机。它表
618计计 ASP 3 高级编程 下载示一台计算机,如果要检查它的属性,就会发现它的很多属性与用户对象的一样,当然还有其他一些属性,这些属性包含只属于计算机的信息。
对象的类型称作类。例如,在 A D里,用户是对象类,计算机也是对象类。因用户和计算机是两个不同的类,所以它们能拥有的属性就不一样。在 a d s v w,e x e里,选中的对象的类显示在右边顶上的信息中,在图 2 1 - 1和图 2 1 - 2中都可看见。
类决定了对象拥有什么样的属性,特别是它决定了必有的和可选的属性。必有属性
(Mandatory propertie)是某类中所有对象都必须有值的属性,可选属性 (Optional propertie)的值可能有但不是必须有。一个对象通常除了具有类所定义的必有属性和可选属性之外,再无其他属性。
21.3.3 容器和叶前面已提到,目录树中可作为其他对象的父对象的是容器。而不能这么做的则是叶 ( l e a f )。
一个对象是容器还是叶决定于它所属的类。一些类定义为容器而另一些类则定义为叶。例如,
在 A D里,用户和计算机都是容器。图 2 1 - 1和图 2 1 - 2中的信息中的两行说明了这一点。
C o n t a i n e r行说明它是不是一个容器,C o n t a i n m e n t行说明它可成为哪些类对象的父对象。
这类事情在大多数目录中被定义得很仔细,以确保用户在修改目录的内容时不会破块目录树的结构。如果往目录中添加新的对象,必须把它放在规定的地方,符合目录规则,即哪些类的对象能包含哪些类的对象。当然还有其他的检查,如是否有足够的安全权限!
事实上一个对象是容器并不是说它必须包含其他对象,而仅仅从原则上允许这么做而已。
例如,在 A D里,所有用户帐号从技术上说都是容器,但在作者的用户帐号里,恰巧什么也不包含。
同样,你可能已经注意到目录结构和 Wi n d o w s的文件系统很类似。它们都是同一种层式结构,文件夹在 Wi n d o w s里有时候也称为目录 (这种称呼是从 U N I X系统移植而来的 )。按照这种相似性,文件系统里的文件夹对应目录里的容器,而文件系统里的文件对应目录里的叶对象。但当心不要把这种相似性推得太广。在文件系统中,文件夹的作用仅仅是文件的容器,
除了 Wi n d o w s自动赋予的特定的系统属性 (如创建日期等 )和关于谁能访问它们的安全信息外,
并不真正拥有自己的数据。不能像往文件里存东西那样往文件夹里存大量的文本。相反,在目录里,容器本身也是目录对象,有自己的一套属性。容器与叶唯一的不同之处就是容器可以包含其他的对象。
21.3.4 模式上面已看到了如何通过类来定义对象,以及怎样确定一个对象能拥有什么样的属性和是否是一个容器。这些规则连同其他相关信息,如属性的数据类型 (例如,普通名是一个字符串并且是单值的 ),以及其他任何关于值的范围的限制,并称为模式 ( s c h e m a )。需要说明的是,
模式本身就存储在目录中。可能认为模式是目录的内部细节,且它的实现是目录的事。从某种程度上说这是对的。但有标准的途径去访问模式,这需要模式本身作为目录的一部分存储。
在 A D里,模式被存储在 A D s P a t h为 LDAP://CN=Schema,CN=Configuration,<domain
n a m e >的容器中,这里 domain name是用 A D的格式表示的用户的域名 (见图 2 1 - 2所示的屏幕截图 )。如果检查这个容器,将看到图 2 1 - 3所示的屏幕截图。
第 2 1章 A D S I和 A D介绍 计计 619下载图 21-3 存放模式的容器对象这个对象包含了描述模式的所有对象。从目录树栏的滚动条的长度可以看出,有数目庞大的对象,这是由于 A D有很多属性和类。往下滚动一点并选择描述计算机的模式项,将会看到图 2 1 - 4所示的屏幕截图。
图 21-4 描述计算机的模式
CN = Computer对象说明 C o m p u t e r类的所有实例在目录里应是什么样,这也是它自己的类标识为 c l a s s S c h e m a (类模式 )的原因,它为一个特定的类定义模式!树控件中的其它大多数对象是 a t t r i b u t e S c h e m a (属性模式 ),这意味着它提供了有关某具属性的信息,如它的值的数据类型和是否是多值的。
设置 P r o p e r t i e s列表框来看看 m u s t C o n t a i n属性。这是一个多值的属性,列出了计算机类所有必选的属性的名字。另一属性 m a y C o n t a i n列出了计算机所有的可选属性。
奇怪的是,图 2 1 - 4中的错误消息 E _ A D S _ P R O P E RT Y _ N O T F O U N D说明 m u s t C o n t a i n并不包含任何内容。而在我安装的 A D里,对这个 c l a s s S c h e m a对象,m a y C o n t a i n也给出相同的错误消息。这有点奇怪,因为我们已经看到计算机拥有很多属性。这个表面上的矛盾引出了类的一个重要概念:继承 ( i n h e r i t a n c e )。
21.3.5 继承目录里的类可相互派生 ( d e r i v e )。
如果对 C O M有一定的使用经验,那么你也许已经知道一个接口可从另一个派生。如果接口 A从接口 B派生,那么 A拥有 B的所有属性和方法和 A自己附加的属性和方法。所有 C O M接口都显露三个方法,Q u e r y I n t e r f a c e,A d d R e f和 R e l e a s e,因为它们都由 I U n k n o w n派生。
如果你曾经用 C + +或 J a v a编过面向对象的程序,也许已经接触过类的继承,这与刚才讲到
620计计 ASP 3 高级编程 下载的是一回事。如果类 A从类 B派生,则类 A实现类 B的所有成员函数和成员变量并有属于它自己的成员函数和成员变量。
上述原则同样适用于目录的类,如果类 A是 B的继承类,那么实例 A可以具有实例 B的
c l a s s S c h e m a对象中所定义的必选和可选属性 (注意,这里用了“可以”这个词,但对于必选属性,用“必须”或许更恰当 ),还有 A自己的 c l a s s S c h e m a对象中的那些属性。
可以通过已有的类来生成新类。在 C + +里,甚至允许有抽象类 ( a b s t r a c t ),这些类是专门为派生而定义的。实际上抽象类是不能真正创建它的对象的。 C + +程序员将看到目录中的抽象类与 C + +里的抽象类作用相同。
这解释了 a d s v w,e x e屏幕右边上方标记为 Derived From的行。这行给出了当前被查看的对象的类的父类的名字。观察图 2 1 - 4,会发现类 c l a s s S c h e m a和 d M D (包含所有模式项的对象的类 )都是从一个名叫 t o p的类派生的。 C o m p u t e r类是从 U s e r类派生的 (听起来有奇怪,
但这是有意义的,因为 C o m p u t e r类需要实现 U s e r类的几乎所有的属性 ),而 u s e r 是 从 包 含 了 针 对 一 般 人 的 更 广 义 的 信 息 的
o rg a n i z a t i o n a l P e r s o n类派生的。
事实上,就 A D而言,可以更深入一些。在 A D (就这问题而言,
可以是任何符合 L D A P 的目录 )里的所有对象都有一个名叫
o b j e c t C l a s s的属性。它是多值的,它的值是继承树中通往这个类的所有 (祖先 )类的类名。对于一个 C o m p u t e r类,其类链如图 2 1 - 5所示。
如果在 A D浏览器里的 P r o p e r t i e s列表框中选择 o b j e c t C l a s s项,
将看到这一点,如图 2 1 - 6所示。
图 21-6 在目录浏览器中显示的类链
t o p类在 A D里起着重要的作用。这是一个通用的类,有数目庞大的必选和可选的属性。
M i c r o s o f t认为它对 A D中的所有对象都有用。任何符合 L D A P的目录中的所有对象归根结底都是从 t o p类派生的。
到目前为止,你已经获得了关于目录结构的很多信息,这些信息将来我们都需要。现在再进一步讲一下目录,以避免不明白图中列出的其它部分是干什么的。 C L S I D是一个唯一的
G U I D (用来标识对象的类 )。标识为 Primary Interface的行是与 A D S I有关的,与 A D无关。使用
A D S I时,你会发现需要创建 C O M组件来访问目录对象,一个 C O M组件对应目录里的一个对象。因为正在讲述 A S P,所以仅使用 A S P里的 I D i s p a t c h接口与 C O M对象通信。 P r i m a r y
I n t e r f a c e是 C O M对象的“真正的”接口的 I I D,也就是当用 V B或 C + +编程时可能直接使用的接第 2 1章 A D S I和 A D介绍 计计 621下载图 21-5 目录中的类链口,用 V B或 C + +编程时避免使用 I D i s p a t h。
帮助文件名和环境提供了类对象的帮助信息。 O I D (对象标识符 )是另一个唯一标识符,不仅标识类,还标识其他信息,如定义这个类的组织的名字。我们并不需要关心对象标识符。
21.4 目录的特征对 A D的结构我们已有一些概念。前面所讲的有的部分是 A D特有的,有的部分不是 A D特有的,而是所有符合 L D A P标准的目录所具有的。对于前面所讲的一切,一般来讲,如果不是实现细节,则大多数目录都满足。
到目前为止,我们已经知道目录是一个分层的信息库,而且知道它包含着对象,对象包含着很多属性。
还有其他一些大多数目录的典型特征。
21.4.1 优化查找目录的主要目的是当需要时可以到它里面去查信息。因此,通常是按读操作的最优化实现的。这基于经常地读目录而不是写目录的假设。 A D正是这样优化的。
21.4.2 查找功能前面所有的屏幕截图演示的都是浏览操作,也就是看看目录中不同的容器里有什么内容。
更经常的情况是进行查找。查找就是根据一个对象的一个或多个属性找出它在目录中的位置。
例如,可能需要找出所有的两个月没有注册的用户帐号以禁用它们。尽管从屏幕截图中已经看到,所有的用户帐号恰好全部存在于 A D的同一个容器里,但要知道,实际不总是这种情况,
通常要执行一下查找操作以确定已找到了所有的用户帐号。
目录一般支持非常复杂的查找请求。找出所有的两个月没有注册的用户帐号只是一个很简单的请求。一个更复杂的请求可能是:显示注册名以,a”开头、两个月没有注册的除域管理者以外的所有用户帐号。所有符合 L D A P标准的目录,包括 A D,都支持这种复杂级别的请求,这使查找成为一个非常强大的概念。
21.4.3 开放性这意味着目录可以通过某一标准协议集进行访问。最常用的是 L D A P协议。通过开放的标准协议使目录具有可访问性,这使得编写与它通讯的客户端应用程序十分容易,可以不需要去学习那些厂家专有的 A P I。
A D符合 L D A P标准,并且随着学习 A D的不断深入,你会发现如何构造和访问数据是非常重要的。 A D有很多的特性,这些特性都是 L D A P需要的。
21.4.4 事务处理很多商业数据库有相当完善的支持事务和当操作失败时回滚事务的功能。 SQL Server属于这个范畴。 A D O包括支持事务的方法,前提是数据源实现事务。在这里提到这个问题的原因是事务处理在目录里通常并不是至关紧要的。
622计计 ASP 3 高级编程 下载
21.4.5 复制检查一个软件是否有用的通常方法是看能否在企业环境具有可扩展性,目录也是如此。
很多目录 (包括 A D )支持可扩展性的方法之一是允许它们自己被复制。换句话说,可以将目录拷贝到多台机器上。对于 A D,任何一个是域控制器的计算机都将存储一份 A D的拷贝。
有一个问题摆在我们面前:怎样确保不同拷贝里的内容是一致的。这问题也将潜在地引发大量的网络数据流,因为每个拷贝都试图使自己保持与其他拷贝一样。的确,如果不小心,
由这个问题产生的网络数据流可能会很容易将复制的初衷 (可扩展性 )破坏掉。
为解决这个问题,可借助于目录的另一个特性。前面已提到,完善的事务处理并不是目录最优先考虑的。现在需要增加一点,当目录里同步不同的拷贝时,只要更新最终被执行了就可以了。设计时 A D就是这个观念。一份拷贝中允许有过时信息,但将在一段时间后与最新的版本同步。 A D执行一些完善的算法来确保这一点。
21.5 常见目录以上讲了 A D是什么和能做什么。下面介绍通常使用的可由 A D S I访问的其他目录。
21.5.1 Netscape目录服务器这是个可从 N e t s c a p e公司得到的通用的 L D A P目录。这里的“通用”,意思是可以存储任何内容。它是按具有高度可扩展性、分层数据存储、按读操作优化的原则设计的,而且有一个只有少量限制 (为维护与 L D A P的兼容 )的模式,你完全可以自己定义。
21.5.2 IIS元数据库这是互联网信息服务器 ( I I S )的配置数据的数据库。可通过 A D S I访问它和 We b站点上所有虚拟目录的细节。然而,元数据库 ( m e t a b a s e )却不遵从 L D A P标准。
21.5.3 Exchange Server目录和站点服务器成员目录之所以把这二者放在一起是因为它们很快将与 A D合并,将不再把它们作为分离的目录。
它们都是符合 L D A P标准的。 Exchange Server目录提供如地址和分布列表等信息给 E x c h a n g e
S e r v e r,而站点服务器成员目录存储了标识访问过该站点的用户的数据,用于产生为这些用户定制的网页并提供专门的安全性支持。
21.5.4 Netware 目录服务这是 A D在 N o v e l l网里的等价物,像 A D一样存储了用户帐号、网络资源和安全权限等信息。
但是,它不遵从 L D A P标准。
21.5.5 Wi n N T
我把它放在最后,严格说来它根本就不应该在这个列表里。 Wi n N T是一个虚构的目录,
是作为 A D S I提供者注册的 C O M组件集。换句话说,它允许通过 A D S I存取目录。这些组件搜集网络中用户和计算机帐号的信息以及在不同机器上运行的服务。这些信息被汇集起来并发第 2 1章 A D S I和 A D介绍 计计 623下载送给客户端,好像它是一个单独的目录。
这有两个理由。首先,考虑到很多网络用的还是 NT 4.0域控制器,而且其中很多在一定时间内还不能升级到 Windows 2000(发布 A D S I和 Windows 2000之间有着 1 2个月的间隔 )。很显然,如果这些系统里的用户使用脚本语言和自动化 C O M组件,他们不能访问 A D提供的用于访问域信息的任何功能,这将是很糟糕的事。 Wi n N T提供者满足了这种要求。
另外,Wi n N T允许访问属于各个机器的一些信息,例如运行 N T服务。缺省情况下,这些信息并不存储在以域为中心的 A D里。
21.6 ADSI的适用范围图 2 1 - 7表示了一个客户程序 (典型的 A S P页面 )用 A D S I访问目录时,各种各样的软件联系在一起的方式。
图 21-7 客户程序与目录和其他软件之间的联系图 2 1 - 7表明 A D S I介于目录和客户程序之间。可把它想像成一套能翻译客户所使用的 A P I
的组件,这些 A P I用于对目录的访问。 A D S I是标准的基于 C O M的 A P I,A D S I是客户程序唯一需要了解的 A P I。从这种程度上,A D S I和 A D O的工作方式相差不多。
注意图 2 1 - 7中标出了客户程序通过网络的可能点,即实线与虚线相交的点。 A D S I提供者是进程内的组件,因此被放在运行 A S P页面的机器上。另一方面,目录服务程序可能被放在另一台机器上。在 I I S里,因为是在 I I S下运行 A S P页面,所以 I I S肯定在 A S P页所在的同一台机器上!然而当在 V B或 C + +里用 A D S I时不一定是这样,这也是为什么在网络中列出了 I I S元数据库的原因。
A D S I,和 A D O一样,使用了一系列的提供者。一个 A D S I提供者是一个能访问目录集或某个特定目录的 C O M组件集。安装 A D S I时,会发现它附带一些 M i c r o s o f t写的标准提供者 (称
624计计 ASP 3 高级编程 下载网络:机器间的边界网络:机器间的边界
ASP 页面
(客户)
ADSI LDAP
提供者
LDAP
协议活动目录目录其他 LDAP
目录关于网络中计算机的信息元数据库
ADSI WinNT
提供者
ADSI IIS
提供者为系统提供者 )。所能得到的提供者某种程度上依赖于所安装的软件,它们一般包括:
LDAP提供者:能访问任何符合 L D A P标准的目录。
Wi n N T提供者:能访问 N T 4控制的域中的机器上的信息。
IIS 提供者:能访问 I I S元数据库。
NWCompat和 N D S提供者:能访问 N o v e l l目录。
你可能已注意到这正好与前面所看到的常见目录的列表相对应。
请注意,尽管这些提供者被不同的组件实现,但它们一般提供相同的接口。
本章将主要讨论 L D A P和 Wi n N T提供者。用 Wi n N T提供者来浏览它显示出来的目录,用
L D A P提供者浏览 A D。
注意没有单独的,A D提供者”,因为 A D完全符合 L D A P兼容标准,L D A P提供者完全能满足需要。这也是为什么 A D里所有的 A D s P a t h s都以,L D A P:,开头的原因。
21.7 LDAP的适用范围前面已经说明,L D A P是一个访问目录的标准协议。从这方面讲与 A D S I很相像,这可能会让人感到奇怪:为什么有两个标准,为什么图 2 1 - 7中先通过 A D S I,再通过 L D A P来访问 A D
和其他 L D A P目录。
L D A P不是一个 M i c r o s o f t标准,是一个被承认了的工业标准。它不是为脚本语言而设计的标准,相反被设计成能够提供一种普通的传输方式,使得在目录里的查询等操作能沿网络传输。如果读一下 L D A P自身的规范 (RFC 2252),将会发现它充满了信息格式等内容。其辅助规范 ( R F C 2 2 5 3 ~ 2 2 5 6 ),更是包含了几乎只与高级程序员有关的内容,如 L D A P使用的 CN =
w h a t e v e r格式 (称为区别名,distinguished name)的定义。
R F C是 I n t e r n e t上建议使用的定义协议的文档。最终在给定的 R F C里提出的建议将被正式做为一个标准接受,这种情况下 R F C提供了协议的最后定义,上面提到的与 L D A P相关的 R F C 就是这样。可在下面网址找到 R F C的列表,h t t p,/ / w w w.
i e t f,o rg / r f c /。
L D A P确实引入了一个 A P I,这是一套 C语言风格的函数。如果用 C或 C + +编程,这当然很好,如果用 A S P编程,它恐怕不太好使用。
相比之下,A D S I是 M i c r o s o f t定义的,并不是工业标准。 A D S I的定义着重在最终客户端可
“看到”的接口。对于我们,客户是 A S P页面,尽管客户程序也可用 C + +,V B和其它众所周知的语言编程,但现在关注的是 A S P页面的情况。 A D S I的定义里没有任何关于怎样与目录服务通信的内容,也没有任何关于网络信息传输协议的内容。从这个意义上,A D S I有时被看作客户端的 A P I;它用来定义客户程序使用的 A P I。客户程序需要关心的只是能有一个 A D S I提供者与需要的目录通信,而这个提供者如何与目录通信是实现的细节,这与客户程序无关。
从这段说明不难看出 A D S I和 L D A P是怎样结合在一起的。一方面,有了用于客户端脚本程序的容易使用的 A P I的规范,另一方面,有了用于在网络上与目录服务通信的优良协议。如果能编写一个使用这个协议的 A D S I提供者,则就拥有了脚本程序用来访问响应这一协议的任何目录服务的提供者。这就是所谓的 ADSI LDAP提供者。可以将其想像成在 L D A P和 A D S I之间转换的组件。可用 ADSI LDAP提供者来访问任何遵循 L D A P标准的目录,包括 A D、
第 2 1章 A D S I和 A D介绍 计计 625下载
Exchange Server目录和 N e t s c a p e目录服务器。这就是为什么图 2 1 - 7中有几个目录可以通过
A D S I和 L D A P链进行访问的原因。
21.8 绑定到一个 A D S I对象在这一节中将开始编一些程序。首先,使用 Wi n N T提供者,然后与 A D进行比较。因为这能确保即使在 NT 4.0环境下这些程序仍能运行,还因为 Wi n N T毕竟有更简单的目录结构,使得对 A D S I的介绍大大简化。等到有更多的编程经验时,再回到 A D。
用 V B S c r i p t绑定到一个 A D S I对象很简单,只需向 V B S c r i p t里的 G e t O b j e c t方法提供对象的
A D s P a t h,如下所示:
运行了这一句后,o b j D o m a i n将拥有一个 ADSI COM组件的引用,通过使用 A d s P a t h
,Wi n N T,/ / To p O f T h e P o p s”访问这个对象。因为现在运行的是 NT 4.0中的 To p O f T h e P o p s域,
这个对象由 Wi n N T提供者提供,代表我们的域。
不论使用什么样的提供者,绑定到一个对象都是这样的步骤。例如,如果想用 A D来看一下自己的用户帐号,可以这样:
在其他的例子里,直接使用了 A D s P a t h,这是因为我们对它及其结构非常熟悉。
如果不能确定一个 A D s P a t h,一个好办法是利用 a d s v w,e x e来浏览一下整个目录。稍后,讲到查找时,将不需要提供 A D s P a t h来定位对象,查找操作将找到它们。
注意到使用不同的提供者是多么容易了吗?不需要像在 A D O里那样为设定一个连接字符串而烦恼。每个对象的 A D s P a t h都是以提供者的名字打头,紧接着是,,/ /”,因此 G e t o b j e c t仅根据 A D s P a t h就能知道需要哪个提供者。当提供了正确的 A D s P a t h时将得到指向正确组件的引用。
A D s P a t h里,,/ /”后的具体格式决定于具体的提供者,从前面的例子中会发现 Wi n N T以
,/”分隔组件,而 L D A P以“,” (逗号 )分隔。还有,从左至右,Wi n N T是下行目录,而 L D A P
是上溯目录。还可看出开头的 Wi n N T或 L D A P是大小写敏感的,但后面的字符串则不敏感。
21.8.1 ADSI对象和 D i r e c t o r y对象前面已经强调过不要把 C O M对象和目录对象混淆,然而可能会发现 G e t O b j e c t给出的总是对 C O M对象的引用。这怎么办? A D S I做得很聪明。你得到一个 C O M对象 (即一个组件 )的引用。
这组件存在于本地的机器上,甚至是进程内的组件,除非由 C O M +进入运行用户的 A S P页中的。
这组件不是目录里的对象,但它装作是目录里的对象,可说它是目录里的对象的代理。尽管有些情况下需要注意到他们之间的区别,但就一般应用程序而言,可把它看成目录对象自身。
所以在说明了要注意 C O M对象和目录对象之间的区别之后,在编写 A S P页时,可把它们当做同一回事。以下就是这样做的。
然而,仍需意识到这种区别,以便知道程序代码到底是怎样执行的,但在大多时间它并
626计计 ASP 3 高级编程 下载不影响编写的代码。稍后,我们将指出在哪几种情况下这种区别很重要。
类似地,还将研究目录对象属性与组件的自动化属性的不同。当开始编程时你会发现在这方面区别更明显,但很多时间将会发现 A D S I里组件的自动化属性就像真实目录属性一样。
由于 Wi n N T提供者装作它正在访问一个正确的目录,这里有很多伪装的操作!但这些都是有益的,这些使 Win NT成为一个易用的 A P I。
21.8.2 查看 A D S I对象的属性下面将把上面的小代码段扩展成为一个与 Wi n N T里的域对象绑定的 A S P页页,并且显示此对象的一些基本信息。这页面称为 D o m a i n I n f o,a s p,运行结果如图 2 1 - 8所示。
图 21-8 运行 D o m a i n I n f o,a s p时的窗口以下是产生图 2 1 - 8屏幕的代码:
第 2 1章 A D S I和 A D介绍 计计 627下载我已使这个页面尽量简单,因为这是本章的第一个 A D S I例子,所以它甚至不包含任何错误检查。 On Error Resume Next确保在发生错误时程序忽略错误而继续前进,如果显示一个属性时出现问题,则程序继续显示其他属性而不去查找错误的原因。
你理解这段代码应该不会有什么困难。它绑定了刚才描述的 A D S I对象,然后列出了一些自动化属性的值。这些属性有:对象的名字,A D s P a t h类、模式以及父对象的 A D s P a t h。模式可能是唯一新的属性。它包含了类模式对象的 A D s P a t h,而类模式对象包含了这个对象的必选和可选的属性。名字在 A D里指的是普通名 ( C N )。一般来讲,C N是 L D A P的术语,A D S I则用 N a m e。
在幕后我们实际上使用了一个名叫 I A D s的接口。所有的 A D S I目录对象都提供这个接口,
它提供了很多给出对象的基本必需信息的自动化属性以及一些得到和设置模式里定义的目录对象的属性的方法。
尽管还没有使用 I A D s提供的任何方法,但刚才几乎演示了它所有的属性。 (有一个例外—
G u i d它给出了一个唯一的 G U I D,它依赖于目录,指出对象的类或某个实例,但本章不会用到 G u i d )。尽管还没有碰到过 I A D s的方法,为了方便仍将把它们全列出来。在没有进一步讲一些概念之前,你可能对这些方法的解释不理解,请暂时将这张表作为参考。 I A D s属性如表
2 1 - 2所示。
表 21-2 IADs的属性及说明属 性 说 明
N a m e 存储对象的名字,对于 L D A P提供者,这通常与 L D A P普通名一样
A D s P a t h 存储对象的 A D s P a t h
C l a s s 存储对象的类
S c h e m a 存储描述这个实例对象所属类的类模式对象的 A D s P a t h
P a r e n t 存储包含这对象的对象的 A D s P a t h
G u i d 存储一个能唯一确定这个对象的 G U I D,这个属性不总是被实现注意所有的 I A D s属性都是只读的。
I A D s方法如表 2 1 - 3所示。
表 21-3 IADs方法的参数及说明方 法 说 明
G e t 检索模式里定义的一个属性的值
G e t E x 与 G e t类似,但返回值的格式不同
P u t 设置模式里定义的一个属性的值
P u t E x 与 P u t类似,但包含与多值的属性相对应的更多的选项
G e t I n f o 从目录服务发送数据更新高速缓存
S e t I n f o 从高速缓存取数据更新目录服务
G e t I n f o E x 与 G e t I n f o类似,但通过只拷贝某些指定的属性来实现对网络调用的优化在处理 A D S I时你会逐渐熟悉这些方法,因为它们是获得和设置目录对象的信息的基础。
因此,所有代表目录对象的组件上必须有提供这些方法的接口。
21.9 浏览目录:枚举容器的所有子对象通过上一节论述得知绑定一个目录对象是非常简单的,尽管实际上绑定的是包装该目录
628计计 ASP 3 高级编程 下载对象的组件,但 A D S I使这看起来几乎是一回事。在这一节中,将说明列出一个对象所有的子对象也是非常容易的。
下面用另一个例子来实现,称为 U s e r B r o w s e,a s p。这个 A S P页面例子用 Wi n N T提供者列出了域里所有的用户帐号。域里所有的用户帐号都是域对象的子对象。所以真正需要做的是绑定到域对象,然后列出它所有的子对象,这恰好就是 U s e r类。
以下是代码:
运行结果如图 2 1 - 9所示。
观察一下代码,显示用户对象的名字和 A D s P a t h采用的是通常方式。有趣的一点是如何枚举他们:
第 2 1章 A D S I和 A D介绍 计计 629下载图 21-9 运行 U s e r B r o w s e,a s p时的屏幕界面这段代码表示,对象 (这里是容器 )同 C O M集合一样被实现,所以能用一个 F o r.,,E a c h循环枚举它们的子对象。
开始循环以前,首先设置域对象的 F i l t e r属性的值。这个属性包含了一个字符串数组,其作用是指定需要列出的目录对象的类。在 Wi n N T目录里,域对象包含的不仅有用户帐号,还有域中的工作组和计算机帐号。现在不需要其它对象,因程序仅对用户 ( U s e r )感兴趣,所以程序设置了过滤器以指明这一点。如果这参数是空的,那么将返回所有的子节点。
或许你已经注意到了 F i l t e r并不是 I A D s定义的属性。很明显域对象必须提供另一个接口。
这里所使用的接口称为 I A D s C o n t a i n e r,所有是容器的目录对象都实现它。为了便于参数,表
2 1 - 4和表 2 1 - 5中列出了 I A D s C o n t a i n e r所有的属性和方法。
表 21-4 IADsContainer的属性及说明属 性 说 明
F i l t e r 指出需要列出的子对象的类
H i n t s 与 F i l t e r相似,但它指定的是不返回的对象的类,它限制了属性从子对象里拷贝,因此可最大限度地减少网络访问
C o u n t 符合 F i l t e r条件的子对象的数目。注意这个属性并不总是被实现。例如,目前 Wi n N T
提供者就还没有实现它从表 2 1 - 5中可以看出,在目录里移动和创建对象时,I A D s C o n t a i n e r正是所需要的接口。
一般而言,通过在被操作的对象的父对象中调用 I A D s C o n t a i n e r的方法执行这一类操作。因为只准备用一章讲 A D S I,所以将不探讨怎样增加和移动目录项。
630计计 ASP 3 高级编程 下载表 21-5 IADsContainer的方法及说明方 法 说 明
M o v e H e r e 将一个目录对象从别的地方移动来作为本对象的一个子对象。可用这个方法来移动或重命名对象
C o p y H e r e 与 M o v e H e r e类似,但它是将指定的对象拷贝一份
D e l e t e 从目录中将本容器的一个子对象删除掉
C r e a t e 按参数中指定的名字和类创建本对象的一个子对象
G e t O b j e c t 与 V B的 G e t O b j e c t类似,但只能获得对本容器的子对象的引用,所以使用时不需要指定完整的 A D s P a t h,而只需要指定对象的名字即可当然,I A D s C o n t a i n e r的方法不是由 I A D s接口提供的这一事实对 A S P代码来说是完全透明的。无论如何,代码是通过 I D i s p a t c h调用方法,所以不需要意识到现在正面对着两个不同的接口。
注意,如果要在目录中上行而不是下行,事情有点复杂。需要对象的 P a r e n t属性,但是因为仅给出了对象的 A D s P a t h而不是对它的引用,所以还需要单独用 A D s P a t h来绑定对象,如下面代码:
I A D s和 I A D s C o n t a i n e r是关键的接口。另外还有很多 A D S I接口,但它们一般是由特定类型的对象提供的特殊接口,与初学者无关。
21.10 使用模式定义的属性前面已经使用了 I A D s的自动化属性了解了对象的基本信息。但对象很可能还有更多的在模式里定义的属性。一般说来,不能像访问自动化属性那样访问它们,因为如果这样的话,那就意味着任何设计相关
C O M接口的人都能预言模式将定义什么。
这显然不可能,因为如果要在目录打开后进行维护,A D S I接口必须用于一般目录而不是某些特定的目录。 I A D s有一些将属性名作为参数以获取或设置属性值的方法。这些方法是 G e t,G e t E x,P u t和
P u t E x。这种方式额外的一个优点就是,
可以不用事先知道属性的名字就能列举一个目录对象的所有属性。
下面的 A S P页就是这样做的。这种情况下,它绑定到 Wi n N T里一个包含用户帐号细节的对象,并且使用模式遍历所有的可选和必有的属性,如图 2 1 - 1 0所示。
注意到有些属性没有值。这也许是第 2 1章 A D S I和 A D介绍 计计 631下载图 21-10 ADSI属性浏览屏幕界面因为这些属性值是用 A N S I字符集无法显示的数据类型 (这种情况下相关 R e s p o n s e,Wr i t e的语句会出错 ),也许它们是可选属性,碰巧没有设置相应的值。图 2 1 - 1 0也说明了 Wi n N T里的用户对象没有任何必有属性,因为,Mandatory Properties”表里没有任何项。
下面是 A S P代码:
632计计 ASP 3 高级编程 下载对于这些代码还需增加一些新的代码。首先,以一般方式绑定用户对象,在这种情况下,
需要增加一些错误检查。
现在枚举所有的可选和必有的属性。因为需要类模式对象,所以绑定类模式对象:
现在显示类模式对象的 A D s P a t h,这一步并不是必不可少的,需要强调一下这个对象只是一个普通对象,可像对待其他目录对象一样对待它,而且对其访问也只是使用了极为普通的
A D S I组件。
如果安装了 a d s v w,e x e,那么可以用它向下浏览目录并找到 Wi n N T模式对象。你将在
,Wi n N T,/ / < D o m a i n N a m e > / S c h e m a”的容器里找到它们。
接下来的步骤使用了类模式对象的一对新的自动化属性,M a n d a t o r y P r o p e r t i e s和
O p t i o n a l P r o p e r t i e s。这两个属性包含了列有可选和必有属性名称的数组。它们由另一个现在还没有讲过的接口 ( I A D s C l a s s )实现,I A D s C l a s s接口由模式对象提供。
因为数组里的每一个字符串是一个必有属性的名字,所以能使用下面的代码显示它们的名字和值,这段代码是从上面的 P r o p e r t y B r o w s e r页简化得到的:
类似地,可用 O p t i o n a l P r o p e r t i e s数组列出所有的可选属性。
你可能会奇怪为什么使用名为 M a n d a t o r y P r o p e r t i e s和 O p t i o n a l P r o p e r t i e s的自动化属性,因为先前提到 A D有名为 m u s t C o n t a i n和 m a y C o n t a i n的属性。事实上在 A D里用它们当中的任何一对都有效 (但在 Wi n N T里不是 ),但是用 m u s t C o n t a i n和 m a y C o n t a i n时它需要用 G e t方法,因为那些名字的没有自动化属性,因此使用:
这实际是不同标准之间存在的问题。 L D A P使用 m u s t C o n t a i n和 m a y C o n t a i n。而 A D S I使用
M a n d a t o r y P r o p e r t i e s和 O p t i o n a l P r o p e r t i e s。因为本书正在用 A D S I的 A P I,所以下面还是统一用第 2 1章 A D S I和 A D介绍 计计 633下载
A D S I的方式比较好一些。
2 1,11 Get和 G e t E x
尽管例子 P r o p e r t y B r o w s e,a s p看起来像是要列出所有的属性,但却有一个较大的缺陷:仅对单值的属性有效,而不能显示多值的属性。问题是下面代码的第五行引起的:
这行程序假想 G e t方法返回的变量都是可打印的。但实际上有许多理由证明情况不总是如此。事实上,G e t返回一个 Va r i a n t,它的值是否可打印决定于 Va r i a n t里包含的数据的类型。这属性可能根本不包含任何值 (返回一个空 Va r i a n t,或者该值可能是某种二进制格式的。还有,
一些属性返回对其他对象的引用,例如 A D里的对象的 n T S e c u r i t y D e s c r i p t o r属性就这样,这已超出了本章讨论的范围。
然而,属性内容不能打印的原因之一是属性可能是多值的,在这种情况下 G e t将返回包含一个数组的 Va r i a n t。
多值属性的存在使 I A D s提供了两个返回属性值的方法 G e t和 G e t E x。它们的区别是:如果只有一个属性值则 G e t将其作为 Va r i a n t返回,如果有多个属性值则 G e t返回的 Va r i a n t包含一个属性值的数组。而 G e r E x返回的 Va r i a n t总是包含一个属性值的数组。如果属性只有一个值,则这个数组将只有一个元素。
很明显,到底用哪一个取决于编程人员的喜好和在具体情况下哪一个更方便。通常,如果不知道一个属性是单值还是多值的,很可能用 G e t E x,因为用 G e t则不知道它的返回值的格式。在 P r o p e r t y B r o w s e,a s p页里选择用 G e t是因为已经知道 Wi n N T的用户对象里没有多值属性。
但如果希望这个页具有更一般的用途,确实需要它能够列出多值的属性。这也是下一个示例所要完成的任务。
要指出的最后一点是,你会发现有些情况下用 G e t或 G e t E x方法能够获得属性,也可以作为自动化属性获得属性。在 A D S I的设计者预料到某些属性会被某些对象经常使用,并因此增加接口提供这些属性做为自动化属性时,会发生上述情况。例如对于 Wi n N T里的用户对象,
以下两行代码效果是一样的:
和:
A D S I的 M S D N文档包含了关于不同的提供者可能提供的属性的详尽细节。
21.12 PropertyBrowseEx示例这个例子与 P r o p e r t y B r o w s e例子相似,但有两个不同点:第一,使用了 G e t E x而不是 G e t,
因此列出了所有的多值属性,并用同样的代码列出了单值属性。第二,对想要查看的对象的
A d s P a t h,它使用了一个 H T M L窗体,允许用户填入 A d s P a t h,而不是在程序中硬编码。这使
634计计 ASP 3 高级编程 下载得能用同一个页面来查看不同的对象和不同目录里的对象。
图 2 1 - 11就是运行时的页面。
如果键入一个对象的 A D s P a t h并点 S u b m i t,将得到与 P r o p e r t y B r o w s e例子非常相似的输出。
图 2 1 - 1 2里查看了作者的域控制器 B i g g y B i g g y的文件服务。这文件服务是负责对来自网络中其他计算机要访问本机的共享文件和文件夹的请求 进 行 应 答 的 N T 服 务 。 它 的 名 字 是
l a n m a n s e r v e r。
这里的程序代码与 P r o p e r t y B r o w s e例子非常 相 似 。 注 意 在 窗 体 中 的 代 码 以 选 定 的
A D s P a t h作为默认值,这样对用户更友好。
第 2 1章 A D S I和 A D介绍 计计 635下载图 2 1 - 11 Property BrowseEx屏幕 1
图 21-12 PropertyBrowseEx屏幕 2
21.13 AD与 Wi n N T提供者比较
A D和 Wi n N T提供者之间有很多的重叠,二者在某种程度上都提供了对相同信息的访问。
636计计 ASP 3 高级编程 下载通过二者中的任意一个显示出的信息都包括域中全局用户、工作组和计算机帐号。除此之外,
Wi n N T提供者还允许获得成员计算机上的 N T本地服务和打印任务的信息。另一方面,A D允许了解域林 (domain forest)的配置信息和系统管理员选择存在那里的任何其他数据。
分别用 Wi n N T和 L D A P提供者查看数据,可看到 Wi n N T和 A D之间更多的不同点。在图 2 1 -
1 3和图 2 1 - 1 4的屏幕截图中用 P r o p e r t y B r o w s e E x,a s p查看用户帐号,分别使用二者的提供者。
图 2 1 - 1 3是 Wi n N T版的用户帐号对象。
图 21-13 Wi n N T的扩展属性浏览窗口图 2 1 - 1 4是同一个用户帐号作为 A D里的一个对象被查看时的屏幕。
A D的屏幕截图里更小的滚动条滑块表明了 A D能为它的对象存储比 Wi n N T更多的属性。
另一方面,大多数可选属性的值是空的,这仅仅是为了万一系统管理员需要使用他们存储信息而定义的。还有,Wi n N T没有必有属性,而 A D有几个,包括前面讨论过的 o b j e c t C l a s s。
o b j e c t C l a s s显示了用户类继承树里所有的类 o b j e c t C a t e g o r y是将在学习如何执行查找时遇到的一个属性。它携带了与 o b j e c t C l a s s类似的信息,但对查找更有效。 s A M A c c o u n t N a m e是用来注册的名字,而且它对应于 Wi n N T提供者里对象的 N a m e。 n T S e c u r i t y D e s c r i p t o r和 o b j e c t S i d包含了对象的安全信息。二者都不能显示,因为 n T S e c u r i t y D e s c r i p t o r实际上是对一个安全描述符第 2 1章 A D S I和 A D介绍 计计 637下载组件的引用,而 o b j e c t S i d是二进制格式的。
通常认为,Wi n N T提供者是一个基本的提供者,只显示了其对象的最基本信息。例如,
它不提供对安全描述符的访问。如果想用最短的代码做一些最简单的事情,则 Wi n N T更易用。
A D里更多的信息是有代价的,要想学会它更困难。如果网络处在一个 NT 4.0主域控制器管理下,那么将因无法访问 A D而不得不使用 Wi n N T提供者。另一方面,用 Wi n N T提供者是无法查找的,所以如果要写一个需要完善的查找机制的 A S P页,就必须选择 A D。
图 21-14 AD的扩展属性浏览窗口
21.14 属性缓存因为目录服务程序可能运行在网络的任何地方,所以访问任何一个属性可能是一个很慢的过程。为了将这个问题的影响减少到最小,每一个 A D S I的组件保留了相应目录对象的一些或所有属性的一个本地拷贝。这个本地拷贝称为属性缓存。因把所有属性从目录拷到属性缓存而使网络阻塞问题减到最少,客户程序可从缓存里取用它想要访问的属性。如果改变了一些属性,那么可以调用一个方法 ( I A D s,,S e t I n f o )把整个缓存写回目录,即更新目录。有一个独立的缓存确实意味着缓存或目录本身都可能有属性的一些陈旧的值,但前面已经说了,对于
638计计 ASP 3 高级编程 下载目录来说这不是一个很严重的问题。客户端程序可在任何时候选择从目录到缓存或从缓存到目录更新数据。
分析一下前面的 I A D s方法的列表,会发现有三个处理这种更新的方法。 G e t I n f o,S e t I n f o
和 G e t I n f o E x。 G e t I n f o根据目录更新整个缓存,而 S e t I n f o则相反。如果仅需要个别的属性,可用 G e t I n f o E x代替 G e t I n f o。
一般而言,修改了属性的值后必须调用 S e t I n f o。你可能以为每次查看属性前总是要调用
G e t I n f o,但实际上不必要。在缓存里,当第一次试图访问一个属性时,组件将检查缓存有没有被预置,如果没有,将隐式地调用 G e t I n f o。只有怀疑拥有的值是陈旧的而想更新时,才需要显式地调用 G e t I n f o。
I A D S的 G e t,G e t E x,P u t和 P u t E x方法,以及自动化属性,只处理属性缓存,而不是目录。
所以,如果要调用 G e t来查看一个属性的值,将只能得到缓存里的值,但当属性缓存没有被初始化时,隐式地调用 G e t I n f o。
属性缓存的处理是需要意识到所使用的 C O M组件与最终想要处理的目录对象之间的区别的一个领域。
21.15 设置属性的值目前讨论的例子都是关于如何读属性的信息,但写入新值也很容易。对于一个单值的属性,仅需要用 I A D S,,P u t方法。例如,如果想改变一个用户帐号的描述,可用以下代码实现:
注意对 S e t I n f o的调用。可以在改变了本地缓存后立即调用它,但如果做完所有的改变以后再这样做效率会更高一些,这样只需要调用一次。
如果要设置一个多值属性,用 P u t E x会比用 P u t更好一些。区别是对于一个多值的属性,
修改数据有几个不同的途径。可能想在当前值里增加一个新值,或替代当前所有的值,或删除一个或几个值。同样,对于可选属性,可能想清除它的所有值。 P u t E x与 P u t作用差不多,
但它有一个附加的参数来指明如何做这些改变。所有的细节都在 A D S I的文档里,在这里就不深入讨论了。
21.16 目录的验证迄今为止,我们举了很多例子了,但一直是假定有足够的安全权限来执行它们。但是,
这一点存在着问题。我们正在处理 A S P页,这意味着页面很可能要运行在互联网客人帐号下。
假设系统管理员的业务非常好,那么互联网客人帐号几乎不可能改变由遵从 A D S I的目录提供的任何数据。它甚至也不允许查看目录里太多的数据,如果试着运行前面的任何一个例子,
就可能会发现迄今为止之所以能侥幸运行成功,仅仅是因为这些例子没有试图修改或浏览一个特别敏感的数据。
所以必须讨论怎样提供更多适当的安全证书的问题。
下一个例子就这样做了。这是一个很简单的例子,它所做的只不过是验证是否提供了适第 2 1章 A D S I和 A D介绍 计计 639下载当的用户名和口令。为了简单起见,所有诸如机器名等信息都硬编码在代码中,如同前面的一些例子,如果从其他站点下载,那么在运行前需要改变一些名字。
这个页面看起来很简单,仅仅说明了它起的作用,运行的屏幕图如图 2 1 - 1 5所示。
关键的是这几行:
从这里可以看出验证分两步。第一,用 G e t O b j e c t绑定到目录顶端的对象,即其 A D s P a t h
为提供者名加上冒号的对象,也就是 Wi n N T:或 L D A P:或 I I S,。这个对象称为名称空间对象。
640计计 ASP 3 高级编程 下载图 21-15 ADSI目录验证屏幕然后可以调用名称空间对象提供的一个方法 O p e n D S O b j e c t,来真正返回对所需要的对象的一个引用。 O p e n D S O b j e c t实际上是通过接口 I A D s O p e n D S O b j e c t实现的,而 I A D s O p e n D S O b j e c t
只能由名称空间对象提供。它需要四个参数:所需的对象的 A D s P a t h,想绑定到帐号的用户名和口令,以及一个包含了各式各样的关于验证实现的标志位的整数值,通常设置为 1,并需要基本的普通 Wi n N T / Windows 2000验证。
尽管这个过程看起来并不复杂,但是必须意识到这只不过是因为提供者为验证所做的工作已经被很好地隐藏了。提供者可能需要在幕后模拟另一个用户,或者它可能需要创建一个新的连接。在这里有很多的原因,大部分与安全性有关,为什么会出错,有一些原因在知识库的 2 1 8 4 9 7和 1 5 8 2 2 9文档里讨论了。因此,可能宁愿用
I I S本身的基本验证或 N T L M验证来提供适当的安全证书,而不去依赖 O p e n D S O b j e c t
方法。这也是在本节没有花很多时间讨论 A D S I验证的原因。
21.17 查找这是在本章所要讨论的最后一个题目,它是 A D S I里的最重要的内容之一。如前面所提到的,目录的最重要的方面之一就是它支持复杂的查找。迄今为止,已讲过的所有例子都是依赖于已经知道要绑定到的对象的 A D s P a t h。查找可以避免这个因素。通过某种方式表明“不知道这个对象在目录里的位置,但知道关于它的属性的一些内容”,例如可能是一个名叫
,H e n r y”的用户帐号。
事实上,尽管应用程序查找时将间接使用 A D S I,但是使用 A D S I的事实却被很好地隐藏在幕后。这是因为查找通过 A D S I访问目录的方式实际上根本不直接使用 A D S I,而是调用一些
A D O对象来代替。这些 A D O对象将在内部使用 A D S I提供者的服务。
这样做的理由是因为脚本语言的一个限制。目前,脚本语言只能通过使用 I D i s p a t c h接口同 C O M组件通信,不能直接调用其他接口的方法。这还不是个大的问题,因为所需的所有
A D S I接口都是双重的接口。但是,A D S I用来实现查找的接口叫作 I D i r e c t o r y S e a r c h,它是一个定制的接口,不能被脚本客户直接使用。
以上情况与 A D O和 OLE DB的情况很相似。当使用 A D O时,真正访问数据源的不是 A D O
组件,而是 OLE DB组件。 A D O组件存在的唯一理由是代表程序调用 OLE DB组件,这样就能解决 OLE DB不是为脚本语言设计的问题,而且这样也能使用定制的接口。现在需要做的另外一步是,A S P页必须访问一个 A D O组件的服务。这个 A D O组件进而访问一个 OLE DB组件,
最后 OLE DB组件用一个用于 A D S I的 OLE DB 提供者来调用 A D S I接口里的方法,来访问目录
(在 A D O看来,目录是数据源 )。这个过程如图 2 1 - 1 6所示。
图 21-16 查找目录的过程示意图第 2 1章 A D S I和 A D介绍 计计 641下载客户 ADO OLE DB
目录服务用于 ADSI的
OLE DB提供者图 2 1 - 1 6看起来复杂,但是其客户代码很简单。
在查找时还有一件事情必须意识到。尽管查找在目录里有普遍的重要性,但并不是所有的 A D S I提供者都支持它。 WinNT ADSI 提供者就不支持,不能用这个提供者来进行查找。这是取决于其工作的机制,Wi n N T搜集整个网络的信息,所以在它后面根本没有真正的拥有支持有效查找的基础设施的后端目录。
ADSI LDAP提供者允许查找,并且任何符合 L D A P标准的目录也必须这样,因为查找是
L D A P规范所要求的。因此可以对 A D实施查找,所以最后一个例子将是基于 A D的。
以下的例子演示了这一点。这个例子名为 S e a r c h,a s p,使用 L D A P提供者来实现一个查找。
为简单起见,所有的查找参数已经硬编码在页面中了,它们请求了对目录中所有用户的查找。
图 2 1 - 1 7所示为页面运行情况。
图 21-17 运行 Search.asp 时的屏幕图 2 1 - 1 7 所示 屏 幕 截图 表 明 已经 找 到 了所 有 的 用户,并 列出 了 每 一个 用 户的
s A M A c c o u n t N a m e和 A D s P a t h。紧靠表上方的命令文本是传送到 A D O的产生这个结果的命令。
在看了产生这个屏幕的代码后,将看一下这个文本所需要的语法。现在,你可能注意到命令文本是由页上端的四个字符串组成的:查找基 (search base)、过滤器 ( f i l t e r )、所需属性
(properties requested)和范围 ( s c o p e )。
查找示例的代码是这样的:
642计计 ASP 3 高级编程 下载这里不需要做过多的解释,因为它大部分是标准的 A D O信息,这些在本书的前面已经讲过。我们建立了一个命令并传送一个字符串给命令对象的 E x c u t e方法。注意这里根本没有直第 2 1章 A D S I和 A D介绍 计计 643下载接创建任何 A D S I对象!所谓的新内容就是要传给 A D O连接对象一个字符串以表明要使用用于
A D S I的 OLE DB提供者 ( A D s D S O O b j e c t ),以及命令字符串是如何组织的。
21.17.1 用以查找 A D S I目录的命令字符串回顾一下用来请求查找所有用户的字符串。为了提醒,重新列出如下:
这个字符串由四部分组成,以分号分隔。需要告诉目录服务:
要找什么 (换句话说,查找操作所返回的对象必须满足什么样的条件 )。
在目录的什么地方找。
如果找到了这些对象,对它们的什么属性感兴趣。
对于本例来说,找什么是“任何是用户的东西”;在目录的什么地方找是“任何地方”;对它们的什么属性感兴趣是,s A M A c c o u n t N a m e和 A D s P a t h” 。现在好了。剩下要做的就是怎样把这几条信息按正确的语法转换成目录服务程序所能理解的形式。
先讲一下需要的属性,因为这是最简单的一条。组织一个字符串,它由一个被逗号分隔开的属性名的列表组成,像这样:
下一步是“找什么” 。这本身是一个大的题目。我们将使用查找过滤器 (search filter)。怎样建立查找过滤器是一个很大的题目,所以在下一节将更详细地讨论它。对于本例这个特殊的请求,只需要是用户的所有对象。相应的查找过滤器是:
注意格式,它指明某一个属性必须有某一个值。所有的查找过滤器最后都归结为像这样的一系列条件。指定的属性是 o b j e c t C a t e g o r y,因为在 A D里它包含了对象的一般类型的信息,
所以它对于使用这一类过滤器来说是一个方便的属性。
最后需要指明目录的那一部分是想要查看的。对于本例,假定对用户所处的位置一无所知,所以要指定整个目录。对于其他的查找,也可能对目录的结构有一些了解,并因而对在哪里能找到对象有一个粗略的概念。很明显,所指出的查找范围越精确,查找的速度就越快。
查找通常用于目录的子树。这需要指定子树的两条信息:位于子树顶点的对象的 A D s P a t h
和从这对象向下要找多深。位于子树顶点的对象的 A D s P a t h是查找基,而向下查的深度称为查找范围。
查找基很好理解,因为它只是个 A D s P a t h而已。
查找范围是一个字符串,可以是以下三个值当中的一个:
subtree:如果查找范围是这个值,那么查找将搜索基以下的整个子树。
o n e l e v e l:如果查找范围是这个值,那么只搜索查找基的直接子对象。这与利用
I A D s C o n t a i n e r方法枚举一个容器的内容很类似,但这里能指定更复杂的查找过滤器。
b a s e:如果查找范围是这个值,那么只查找一个对象,就是这个查找基本身。这类查询将返回一个对象或者不返回任何对象,这取决于这个查找基是否满足查找过滤器。看起
644计计 ASP 3 高级编程 下载来没有什么必要实现一个以基作为范围的查找,但 L D A P规范中有一些技术上的理由说明它是有用的。
现在已经具有了足够的信息来看一下命令字符串是怎样组织的:
查找基是,LDAP://dc = To O f T h e P o p s,dc = Fame,dc = com。
这是 A D的根对象的 A d s P a t h。
查找过滤器是,(objectCategory = person)。
这告诉目录服务返回所有的用户对象:
所需属性是,s A M A c c o u n t N a m e,A D s P a t h。
查找范围应为整个子树,所以它的值是,s u b t r e e。
命令文本是由这四个子串按以下格式组织起来的:
<查找基>;查找过滤器;所需属性;查找范围注意查找基是用尖括号括起来的,而分隔字符串用的是分号。还要注意不要加多余的空格。如果加了任何多余的空格以使它更易读,那么,目录服务能否识别该命令字符串就要看运气了 (这取决于把空格加在哪里 )。所以强烈建议不要多加一个空格!
21.17.2 查找过滤器查找过滤器包括一系列的条件。每个条件说明某一个属性必须有某一个值,而且这些条件用逻辑运算符 A N D (与 ),O R (或 )和 N O T (非 )连接起来,若以符号表示分别为,&”,,|”和
,!” 。可以在任何属性值里使用通配符,*”,而且每个条件以及整个过滤器必须用圆括号括起来。
例如过滤器:
将返回所有 s A M A c c o u n t N a m e以 b开头的对象,而过滤器:
将返回所有 d e s c r i p t i o n属性的值包含,a n d”子字符串的所有对象。
注意字符串都没有用引号括起来。
语法里与通常情况不一样的是,运算符,&”和,|”是放在运算对象的前面而不是之间。
例如,如果想表示对所有的其 a A M A c c o u n t N a m e s以 s开头的用户感兴趣,可以这样写:
而如果想要的是 a A M A c c o u n t N a m e s以 s或 t开头的用户,那么将这样书写:
括号保证了或 ( | )条件被先计算。
这语法与 L I S P和一些 H P计算机使用的逆波兰 (Reverse Polish)语法很像。
最后,有一个过滤器你将经常碰到:
这是检索所有对象的标准方式。它之所以生效是因为 (根据 L D A P规范 )所有的对象都必须有一个名叫 o b j e c t C l a s s的属性。这个过滤器说明了 o b j e c t C l a s s可以具有任何值。
这里说明了 L D A P查找过滤器的基础,用它们还可以干一些更高级的事情。欲了解详情,
第 2 1章 A D S I和 A D介绍 计计 645下载请查阅 RFC 2254,在那里,正式地定义了 L D A P查找过滤器的语法。
21.18 小结本章只介绍了 A D S I和 A D的最基础的内容,但凭这些内容已经可以开始用 A D S I来访问目录的内容。 A D S I是一个很强大的工具。用它可以改变口令、增加用户帐户、启动和终止 N T服务、处理打印队列以及管理 I I S自身,所有这一切都通过简单的脚本语言实现。很多这样的操作先前都是 Windows API函数的领域,需要用 C + +写的应用程序来实现。如果希望能够从一个
We b页里做这些事情,将需要用 C + +写一个能从 We b页里调用的组件,以实现所需操作。现在
A D S I出现了,能从 We b页里完成的任务 (尤其是管理任务 )的范围大大增加了。
646计计 ASP 3 高级编程 下载