AD & ADSI入门
热 ★★★★
AD & ADSI入门
作者:闵涛 文章来源:闵涛的学习笔记 点击数:1918 更新时间:2009/4/23 18:59:24
AD简介
Active Directory(以下简称AD)可以认为是一个大的层次结构数据库,集中存储的内容必须遵循AD当前所定义的Schema。我觉得AD中最重要的内容就是Schema,然后是ADSI。
Schema 定义了数据存储的格式。包括类(classSchema),分为抽象类(Abstract)、附属类(Auxiliary)
和结构类(Structure)三种;属性(attributeSchema),分为单值和多值属性;以及类和属性之间的关系,分为可选属性和必要属性。AD中的Schema相当于全局的Catalog,在整个AD的forest中是全局唯一的,任何的修改都会被同步。所以有关Schema的修改需要有Schema Administrators的权限。而且Schema的内容只能增加,不能删除,过程是不可逆的,最多只能禁止一些属性或者类,而且还有诸多限制,详见文档。
在AD中存储的数据被当作一个一个的对象,每一个对象是一个classSchema的实例。都有一个唯一的路径访问。AD中对象的路径由所支持的Provider 决定,Windows 2000默认的Provider有四个,安装IIS的话会增加一个IIS的Provider,对IIS进行管理。通常使用比较多的是LDAP,可以通过这个Provider针对域用户以及其他扩展信息进行访问和管理。WinNT是针对NT4的帐号管理,估计是向下兼容。另外两个是对Netware的DN的访问,对我们而言不太会用到,不赘述了。
ADSI( Active Directory Service Interface)是用来对AD中存储数据的访问接口,我认为他是一个架空的框架,与具体的数据访问无关,只是给上层应用提供一个统一的接口。实际工作的就是Provider,应当是Provider访问数据,然后包装成ADSI要求的形式,这些工作对用用户来说完全透明。
另一个比较爽的地方是ADSI提供了比较好的扩展的方式,你能够非常容易的增加新的类,或者给已有的类增添新的方法。
需要解释一下,虽然ADSI和AD经常一起出现,但是AD和ADSI是两码事,ADSI不仅仅能访问AD,还可以访问IIS以及Netware所存储的数据。你只要按照要求提供相应的Provider,ADSI可以干任何事情。
AD编程
AD的编程 到目前来看涵盖的内容非常多,从最粗糙的使用ADSI对AD中已有的数据访问,到比较高级的扩展AD。我认为扩展AD才是这部分编程中比较重要的内容,因为针对任何具体的应用多绘有自己特定的信息,而应用AD主要是为了利用MS提供的安全性以及分布式存储,如果将这两方面结合起来,就需要为了自身的应用对AD进行扩展。
如果需要为已有的类(接口类)添加方法,那么需要编写AdsExtension类;如果需要在AD中存储扩展信息,就需要修改Schema,增加新的类(classSchema)或者属性(attributeSchema);更进一步的话,完全可以自己实现一个Provider,实现自己的查询和数据存储的方式,这一部分内容已经不仅仅局限于AD了。
通过ADSI访问AD比较简单,实际上是应用WinNT和LDAP这两个Provider。除了通用接口IAds、IAdsContainer、IAdsDirectorySearch等以外,Windows默认提供了一些接口类如IAdsUser、IAdsGroup,当安装了一些基于AD的服务之后,又会增加一些专有接口,如安装Exchange 2000之后,会出现Person,同时扩展了User。
在使用AD的过程中比较重要的一个问题是访问者的权限,如果使用GetObject的方式操作,那么应用程序是以当前登录用户的权限访问AD,很多的写操作是被拒绝的。使用IAdsOpenDSObject->OpenDSObject可以指定操作对象的用户,当然这就需要实现得到指定用户的口令。
第二个需要注意的地方就是AD的Path,有两个最常用的前缀(姑且这么叫吧):CN(Common Name)和DC(Domain Controller)。另外对于LDAP从左到右范围增大,而WinNT从左到右范围是减小,比如访问我的帐号,路径分别为LDAP://CN=mittermeyer,CN=Users,DC=cn,DC=corp,DC=company,DC=com,WinNT://cn.corp.company.com/Users/mittermeyer。另外据说AD是区别大小写的,我看下来他有一种数据类型是区别大小写的字符串,但是路径这里好像无所谓,CN=和cn=都行。
第三个需要注意的地方就是查询语法。查询的话,一共提供了两种方式,一个是IAdsSearchDirectory接口,IAdsDirectorySearch完成查询过程和处理查询结果的全部工作,我个人认为这种方式不太适合VB的程序;另一种方式是使用ADO。AD针对ADO有一个Provider(ADsDSOObject),使用这种方式返回一个ADO.Recordset,处理结果和关系型数据库的查询完全一致,这种方式VB比较容易上手。ADO的方式查询可以使用SQL的语法,也可以使用LDAP的语法;而IAdsDirectorySearch只能使用到的是LDAP的语法。
这一部分比较有趣的是扩展接口,就是写一个接口作为已经存在的接口类的扩展。扩展接口本身只是继承IDispatch就可以了,但是如果需要支持后期绑定,那么还需要实现IAdsExtension所要求的一系列方法,看上去是模板,就是一个套路,所以这部分工作还是比较简单的。 关键是把自己编写的接口和已经存在的接口类关联,嘿嘿!也很简单,只要在注册表里加一项就可以了。(MS想到的方法总是比较容易理解,不过在整体框架那里还是花了很多心思的,所以架子有了扩展就容易了。)例如:以及下就是Exchange加的对User地扩展,它表明Exchange针对User有一个扩展的CoClass--Mailbox,其中包含了两个接口IMailRecipient和IMailboxStore。
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ADs\Providers\LDAP\Extensions\User]
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ADs\Providers\LDAP\Extensions\User\{25150F21-5734-11D2-A593-00C04F990D8A}] "Interfaces"=hex(7):7b,00,32,00,35,00,31,00,35,00,30,00,46,00,34,00,31,00,2d,\ 00,35,00,37,00,33,00,34,00,2d,00,31,00,31,00,44,00,32,00,2d,00,41,00,35,00,\ 39,00,33,00,2d,00,30,00,30,00,43,00,30,00,34,00,46,00,39,00,39,00,30,00,44,\ 00,38,00,41,00,7d,00,00,00,7b,00,32,00,35,00,31,00,35,00,30,00,46,00,34,00,\ 30,00,2d,00,35,00,37,00,33,00,34,00,2d,00,31,00,31,00,44,00,32,00,2d,00,41,\ 00,35,00,39,00,33,00,2d,00,30,00,30,00,43,00,30,00,34,00,46,00,39,00,39,00,\ 30,00,44,00,38,00,41,00,7d,00,00,00,00,00
首先,我们知道attributeSchema和classSchema都存储在同一个层次下,我们可以通过这样的路径访问:LDAP://computername/Schema 之下(另外一种访问路径是CN=Schema,CN=Configuration,<DC=forestroot >),所以在这个Container下我们可以枚举到整个AD中所有的attributeSchema和classSchema。但是我发觉有一个有趣的现象,如果不是以域用户的身份去访问,那么不能得到全集,获得的是Abstract Class和相关的属性,无法得到Structure Class,例如:User。
其次,针对attributeSchema和classSchema都有一些特性: OID(governsID) ,LDAP所需要的对象的唯一表示符,这是一个字符串,但是不同于GUID根据本机信息生成,而是逐级分配的属性结构,最上层由ISO分配,逐级授权,所以很麻烦。MS提供了一个工具OIDGEN.exe,随Windows 2000的Resource Kit发布,我不知道即使是用这样的工具生成的新ID能否运行在实际的扩展系统中,还是必须通过MS的认证。 schemaIDGUID ,用于访问控制目录中控制访问这个类的对象。通过这个ID而不是名称来访问类的对象实例。GUID还是非常好处理的,可以通过Windows自身的API获得。 其他的就是各类名称(cn,LDAPDisplayName,adminDisplayName) ,在不同的工具或者场合显示区别类或者属性,这些名字只要保证全局唯一即可。此外classSchema和attributeSchema各有一些特定的必备属性。
扩展Schema包括以下几部分的工作:新增/禁止attributeSchema,新增/禁止classSchema,修改Property与classSchema的关系。 新增attributeSchema和classSchema,通过IAdsContainer.Create,在Schema存储的路径下新建子节点,然后给必要的属性赋值,最后提交即可。 禁止attributeSchema和classSchema,可以通过“废弃”的方式禁止一个现存的类或者属性。即获得这个classSchema或者attributeSchema,将他的isDefunct属性置为True即可;反之只要将isDefunct属性置为False即可恢复。当然这个操作也存在一系列的限制,例如:禁止一个属性,那么将阻止创建所有所有必须包含该属性的类的实例。 修改Property与classSchema的关系,因为决定每一个classSchema中包含哪些attributeSchema,其实是指定classSchema的“mustContain”和“mayContain”,这两个多值属性(字符串数组)分别表示表示所包含的必要属性和可选属性。反过来,可以通过IAdsClass.MandantoryProperties和IAdsClass.OptionalProperties读取。
暂时没有研究。
实例
枚举对象。下面这个例子枚举了所有通过RC的接口添加到AD中的用户组和帐号。此例中IAdsContainer.Filter 为一个需要筛选的类名数组,如果为空,则表示返回所有类型的对象。
Public Function EnumGroups() As VBA.Collection Dim adDomain As IADsContainer Dim adGroup As IADsGroup Dim nResult As VBA.Collection If m_sAdmin <> vbNullString Then Set adDomain = m_adRoot.OpenDSObject("LDAP://" & m_sExchServer & "/CN=Users," & m_sDomain, _ m_sAdmin, m_sAdminPwd, ADS_SECURE_AUTHENTICATION) Else Set adDomain = GetObject("LDAP://CN=Users," & m_sDomain) End If If adDomain Is Nothing Then Exit Function Set nResult = New VBA.Collection adDomain.Filter = Array("group","user"”) On Error Resume Next Dim sName As String Dim sType As String For Each adGroup In adDomain sName = Right(adGroup.Name, Len(adGroup.Name) - 3) '''' filter "CN=" Debug.Print sName sType = adGroup.Get(cPropCustomType) If Err.Number = 0 And sType = cTypeRC Then nResult.Add sName, sName End If Err.Clear Next Set EnumGroups = nResult End Function
添加一个用户以及用户相关的邮箱,这是一个相对复杂的利用ADSI的示例,其他类似的操作就不赘述了。这里用到的就是ADSI和Exchange针对ADSI中IAdsUser对象的扩展。斜体 的那一段代码颇值得回味,在VB中非常简单的一句话,背后有一套复杂的逻辑。 添加用户组和组邮箱的操作类似,不同的是组邮箱不是一个物理邮箱,而是一个邮箱列表,通过IMailRecipient.MailboxEnabled使之有效即可。
'''' add new user to Domain and create mailbox for it Public Function AddAccountEx(ByVal sAccount As String, ByVal sFullName As String, ByVal sDesc As String, _ ByVal sPassword As String) As Long Dim adDomain As IADsContainer Dim adNewUser As IADsUser Dim oMailStore As CDOEXM.IMailboxStore Dim oExchServer As CExchageManager If m_sAdmin <> vbNullString Then Set adDomain = m_adRoot.OpenDSObject("LDAP://CN=Users," & m_sDomain, _ m_sAdmin, m_sAdminPwd, ADS_SECURE_AUTHENTICATION) Else Set adDomain = GetObject("LDAP://CN=Users," & m_sDomain) End If
[1] [2] 下一页
[学习帮助 ]如图所示,△ABE和△ADC是△ABC分别沿着AB、AC边翻… [办公软件 ]VBA中初始化ADO连接的几种方法 [网络安全 ]计算机无法上网的罪魁祸首—(宰了)删除adware.roo… [Sql Server ]Sql精妙语句--各种求值函数 [Web开发 ]ADO.NET操做数据库 [平面设计 ]Flash loadMovie/loadMovieNum 使用详解 [平面设计 ]功能超强的GIF动画制作软件─Ulead Gif Animator [平面设计 ]AutoCAD常用快捷命令(外加中文说明) [平面设计 ]AutoCAD常用快捷命令(字母类,外加中文说明) [平面设计 ]AutoCAD快捷命令介绍
教程录入:mintao 责任编辑:mintao
上一篇教程: 字符串与二进制互相转化(不包含汉字) 下一篇教程: 用 VB 打开任意盘(硬盘/U盘/光盘)的文件.
【字体:小 大 】【发表评论 】【加入收藏 】【告诉好友 】【打印此文 】【关闭窗口 】
注:本站部分文章源于互联网,版权归原作者所有!如有侵权,请原作者与本站联系,本站将立即删除! 本站文章除特别注明外均可转载,但需注明出处! [MinTao学以致用网]
网友评论: (只显示最新10条。评论内容只代表网友观点,与本站立场无关!)
同类栏目
赞助链接
500 - 内部服务器错误。
500 - 内部服务器错误。
您查找的资源存在问题,因而无法显示。