LDAP使用手册.doc
-LDAP使用手册一、 LDAP介绍LDAP是轻量级目录访问协议的简称(Lightweight Directory Access Protocol).用于访问目录效劳。它是*.500目录访问协议的移植,但是简化了实现方法。二、 目录效劳与关系数据库之间的区别a) 目录查询操作比关系数据库有更高的效率,但是更新效率比关系数据库低b) 目录不支持关系数据库那样的复杂查询,比方两个表的连接。c) 目录不支持多操作的事物完整性,没有方式确认一些操作是全部成功还是全部失败d) 目录能够能好和更灵活的支持子查询和匹配查询e) 目录协议更适合应用于广域网,比方因特网或者大型公司的网络f) 目录的管理,配置,和调试比关系型数据库更简单g) 在使用关系数据库之前,必须首先定义表构造(模式)才可以进展操作。而目录中所使用的模式是由LDAP定义好的一系列类组成的。对于目录中的每条记录中必须属于其中的一个类或者多个类。这些类定义了该记录中可以存储的信息。h) 目录以对象的形式存储数据。信息被组织成树型构造。i) 目录效劳支持分布式存储构造,容易实现数据的扩展,能满足大容量存储的要求。三、 LDAP的优点1:可以存储在其它条件下很难存储的管理信息2:数据平安可靠,访问控制粒度细腻。3:LDAP是一个标准的,开放的协议,具有平台无关性。4:数据分布广,规模可灵活扩大。5:LDAP目录效劳器可以使任何一种开放源代码或商用的LDAP目录效劳器。四、 LDAP模型LDAP模型是从*.500协议中继承过来的。是LDAP的一个组成局部,用于指导客户如何使用目录效劳LDAP 定义了四个模型,包括信息模型,命名模型,功能模型,平安模型。1.LDAP 信息模型(LDAP information model)LDAP信息模型用于描述LDAP息的表达方式。LDAP信息模型包含三局部 EntriesAttributesValuesEntry:Directry中最根本的信息单元,Entry中所包含的信息描述了现实世界中的一个真实的对象,在目录系统中它可以理解为,目录树中的一个节点 。在目录中添加一个Entry时,该Entry必须属于一个或多个object class ,每一个object class 规定了该Entry中必须要包含的属性,以及允许使用的属性。Entry所属的类型由属性objectclass规定。每一个Entry都有一个DN(distinguished name) 用于唯一的标志Entry在directory中的位置。如下列图所示: 根节点DN的命名有多种方法,其中之一就是域名命名法。例如:我们要以公司的网址作为公司目录树的根节点。如sohu. 则根节点的DN应该为 DN:dc=sohu,dc=上图中根节点的DN :dc=e*ample,dc= 而该根节点有两个子节点,ou=people,和ou=servers。 People节点的DN:ou=People,dc=e*ample,dc=RDN:是目录树中节点的相对分辨名。如:People节点的DN: ou=People,dc=e*ample,dc= 而该节点的RDN:ou=PeopleAttribute: 每个Entry都是由许多Attribute组成的。每一个属性(Attribute)描述的是对象的一个特征。每一个属性(Attribute)由一个类型(type)和一个或多个值组成(Value) 如下列图所示:2.LDAP命名模型(LDAP Naming Model)LDAP命名模型定义了如何在目录系统中组织数据以及如何从目录系统中查找数据LDAP命名模型指定将Entry按类似倒立的树形构造进展规划。非常类似于UNI*系统得文件系统如下列图所示:Uni* File SystemA Directory TreeLDAP 目录构造与Uni*系统的文件系统主要有三点不同1. UNI*文件系统有一个根路径,作为访问所有文件和目录的入口。而LDAP 目录构造中的root Entry只是一个特殊的Entry,它包含了目录效劳器的配置信息,通常情况下,并不用来存储信息2. 在LDAP 目录中任何一个节点都可以包含信息,同时也可以是一个容器,也就是说任何一个LDAP Entry都可以有子节点。而UNI*文件系统中的节点要么是一个文件,要么是一个目录。而不能同时是这两种情况。只有目录才可以拥有子节点。下列图表示了LDAP 是一个典型的目录构造LDAP Directory3. UNI*文件系统目录构造与LDAP 目录的第三个区别在于他们的每一个节点的命名不同。LDAP目录中节点的命名和UNI*文件系统目录构造中的节点的命名是相反的。上图示UNI* 文件系统构造,如果要定位到grep节点的话,命名如下/user/bin/grep上图是一个典型的目录构造 第一个节点DN命名为:dn:dc=e*ample,dc=第二个节点DN命名为:dn:ou=People,dc=e*ample,dc=第三个节点DN命名为:dn:uid=bjensen,ou=people,dc=e*ample,dc=我们说每一个Entry的DN是唯一的,就是因为这种数形构造决定了,从根节点到其它任何一个节点的路径是唯一的。RDN:在DN中最左边的容称为相对域名。如ou=People,dc=e*ample,dc=其RDN为ou=People对于共享同一个父节点的所有节点的RDN必须是唯一的。如果不属于同一个节点则节点的RDN可以一样。特殊字符:以下字符如果出现在Entry中的属性值,必须进展转义 # -# ,-, +-+“- - < - < > - > ; - ;如:o=United Widgets, Ltd., c=GB别名在LDAP中可以定义一个别名Entry,指向另外一个Entry。如下列图所示如何创立别名Entry要创立别名Entry,该Entry的object class必须是alias。而且其属性aliasedObjectName的值必须是该Entry所指向的Entry的DN。不过一般情况下应该防止使用别名Entry。会影响性能。而且如果被引用的Entry被删除的话,该Entry就会指向一个错误的结果。LDAP URL由于使用Alias Entry有许多缺点,可以使用LDAP URL或referral代替Alias Entry。3.LDAP功能模型(LDAP Functional Model)LDAP功能模型描述了LDAP 协议可以采用的相关操作,来访问存储在目录树中的数据。 LDAP功能模型包含一系列的操作,这些操作被分为三组。1. 更新操作 包括添加,删除,重命名,修改Entry2. Interrogation Operation用于数据的查询3. 认证和控制 (bind unbind abandon)Interrogation Operation1. The LDAP Search Operation该操作需要八个参数a. base object也可以表示为DN。说明你想要查询direcoty中树的顶点。b. search scopeDN 与search scope两个参数限定了要搜索数据的围共有三个scopeSub 搜索围是包含顶节点在的一棵子树 如下列图其中DN =ou=People,dc=e*ample,dc=Base 搜索围只包含一个节点 如下列图其中DN =ou=People,dc=e*ample,dc=Onelevel 其搜索围是DN所表示的节点下的直接子节点。如下列图其中DN =ou=People,dc=e*ample,dc=c. aliasd. size limit 表示返回的符合条件的Entry的数目,0表示返回所有符合条件的Entry。目录效劳器端返回一个LDAP_SIZELIMIT_ E*CEEDED。e. time limit表示搜索一次所需要的时间,超过时间将停顿搜索。效劳器端返回一个LDAP_TIMELIMIT_E*CEEDEDf. attribute-only该属性是一个boolean值,如果为true ,表示效劳器端之返回所搜索的Entry的属性名称,不返回属性值。g. filter通过该属性可以更准确的搜索结果。就像SQL语句中的条件查询。Filter 分类1.(sn=smith)匹配属性sn的值包含smith的Entry2 (sn=smith*)匹配属性sn的值以smith开场的所有Entry 如smithers,smithsonain等。其中“*表示通配符,代表任意字符。3 (sn=jensen) 匹配属性sn的值听起来像jensen 的Entry。不同的目录效劳器,有不同的实现方法。4 (age>21)或者(!(age<=21)匹配属性age的值大于21的Entry 如果是字符的话,如(sn<=Smith)则按字典顺序进展比拟。5 (telephoneNumber=*)匹配所有属性telephoneNumber的值不为空的Entry6 (&(sn=smith)(age>21)匹配属性sn的值包含smith而且属性age的值大于21的Entry(|(sn=smith)(age>21)匹配属性sn的值包含smith或者属性age的值大于21的Entry(&(mail=*)(!(telephoneNumber=*)匹配属性mail的值不为空,而且属性telephoneNumber为空的Entry7 如果属性的值包含以下五个特殊字符的话必须进展转义 如:(=A*Star) 则必须改为(=A2AStar)h. return attributes该属性表示客户的搜索结果中需要返回的和用户相关的属性列表,如果为空表示返回所有属性。4.LDAP 平安模型平安模型的作用:是提供一个框架,保护目录中的信息不被非法访问。LDAP中的平安模型主要通过身份认证、平安通道和访问控制(ACL)来实现LDAP是一个面向连接的协议,在能够对LDAP目录进展任何操作之前,LDAP客户端必须获得一个到LDAP效劳端的一个连接,在这个过程中需要对LDAP客户端的身份进展验证,这一过程可以理解为用户绑定。LDAPV2 只支持简单的密码验证。LDAPV3 实现了SASL平安框架,SASL为多种验证协议提供了一种标准的验证方法,对于不同的验证系统,可以实现特定的SASL机制。SASL机制代表了一种验证协议。在用户通过验证之后,可以为该用户分配附加的权限,比方一些用户只能查看特定的Entry,而不能修改。一些用户可以查看并且修改所有的Entry等。这一过程可以理解为访问控制。五、 LDIFLDIF通过一个文本文件,用来描述目录数据,可以将目录效劳器中的数据导出到一个LDIF文件中,并且可以将LDIF文件中的数据导入到另一个目录效劳器。即使这两个目录效劳器部使用的是不同的数据库格式。 有两种类型的LDIF文件,第一种用来描述Directory目录数据的,第二种包含更新语句,用于更新现有的Directory条目数据。 第一种文件,容包含两局部:第一局部是DN,第二局部是一系列的属性-值对 如下列图:以上的LDIF文件只包含了一个Directory Entry。可以在一个LDIF文件中包含多个Entry第二种文件,包含更新语句。第一行同样是DN。第二行是更新类型,后边是要更新的属性及值。当然也可以用来添加新的Entry。如下列图:添加一条Entry(注意第二行:changetype:add)如下列图:删除一条Entry 如下列图:修改一条Entry 语法如下:dn: dn of entry to be modifiedchangetype: modifymodifytype: attribute typeattribute type: attribute value添加属性例如删除属性例如或者修改属性值也可以将多条更新语句放在一个文件里,各语句之间用“-分开重新命名Entry或移动Entry语法:dn: 的名称changetype: moddn/changetype类型必须为newsuperior:如果要移动一条则该项表示一个新的节点的deleteoldrdn: ( 0 | 1 )该项表示是否要删除修改以前的不删除newrdn:的新由于一条Entry的DN是由该Entry的RDN 和它的父节点的DN组成的。一条Entry的RDN 是该Entry中的一个属性。就像关系数据库中,主键值可以唯一区区分一条记录一样,在同一个节点下的所有Entry中的RDN必须由唯一标识该Entry属性组成。所以重新命名Entry,也就是重新命名该Entry的RDN。例如如下:执行以上语句后该如下所示:dn: uid=babsj, ou=People, dc=e*ample, dc=uid: babsjuid: bjensen移动一条例如如下:六、 LDAP模式schema如果你使用过关系型数据库,则对模式应该不会陌生。关系数据库系统都是通过表格的形式进展数据存储的。在这之前,我们首先要定义表构造,也即是模式。表构造由一些字段组成,每个字段都有一个类型,以及一些约束条件。这就规定了我们可以存储的信息。上面我们介绍过LDAP目录效劳器中存储的信息是被组织成树型构造进展存储的。和存储信息之前也要定义模式,不过,与关系型数据库系统不同的是,作为LDAP目录效劳器的用户而言,一般不需要自己定义模式,所有实现LDAP协议的目录效劳器,都已经定义好了许多模式,这些模式可以解决我们大局部的信息存储的问题。LDAP模式是由以下一些元素组成的1:Attribute types 属性类型,也就是属性名称。我们已经介绍过,每个属性名称其实也代表着一种属性类型。表示该属性可以存储什么样的信息。2:Attribute synta*es属性语法,该元素表示每个属性名称所存储的信息如何组织。3:匹配规则,每一个属性都有匹配规则,用于数据的比拟。4:object classes,对象类.上面已经介绍过,每个Entry都必须至少属于一个object class。规定了该Entry可以存储那些属性。下面介绍一下LDAP协议中定义的一些常用属性极其含义具体信息看RFC 2252文档属性中文名称描述c名称值为两位代码如:中国:CN 美国:US通用名称dc域名组件如:sohu.dc=sohu,dc=co名称的全名gngavenNamehomephone家庭mail地址mobile移动o组织名称ou部门名称通常为组织机构下的一个部门或者一个大型实体下的一个子实体postalCode邮政编码sn姓,别名st州或者省的名称street街道地址userPassword用户密码uid用户IDdepartmentNumber部门编号displayName显示名称 description描述 employeeNumber员工编号 manager经理下面是一些LDAP协议中定义的object class具体信息查看RFC 2252文档Object class 必须属性可选属性accountuseriddescription $ seeAlso $ localityName $ organizationName $ organizationalUnitName $ hostcountrycsearchGuide $ descriptiondcObjectdcdeviceserialNumber $ seeAlso $ owner $ ou $ o $ l $ descriptioninetOrgPerson->person继承personaudio $ businessCategory $ carLicense $ departmentNumber $ displayName $ employeeNumber $ employeeType $ givenName $ homePhone $ homePostalAddress $ initials $ jpegPhoto $ labeledURI $ mail $ manager $ mobile $ o $ pager $ photo $ roomNumber $ secretary $ uid $ userCertificate $ *500uniqueIdentifier $ preferredLanguage $ userSMIMECertificate $ userPKCS12organizationalPerson继承Persontitle $ *121Address $ registeredAddress $ destinationIndicator $ preferredDeliveryMethod $ tele*Number $ telete*TerminalIdentifier $ telephoneNumber $ internationaliSDNNumber $ facsimileTelephoneNumber $ street $ postOfficeBo* $ postalCode $ postalAddress $ physicalDeliveryOfficeName $ ou $ st $ lorganizationouserPassword $ searchGuide $ seeAlso $ businessCategory $ *121Address $ registeredAddress $ destinationIndicator $ preferredDeliveryMethod $ tele*Number $ telete*TerminalIdentifier $ telephoneNumber $ internationaliSDNNumber $ facsimileTelephoneNumber $ street $ postOfficeBo* $ postalCode $ postalAddress $ physicalDeliveryOfficeName $ st $ l $ descriptionorganizationalRole*121Address $ registeredAddress $ destinationIndicator $ preferredDeliveryMethod $ tele*Number $ telete*TerminalIdentifier $ telephoneNumber $ internationaliSDNNumber $ facsimileTelephoneNumber $ seeAlso $ roleOccupant $ preferredDeliveryMethod $ street $ postOfficeBo* $ postalCode $ postalAddress $ physicalDeliveryOfficeName $ ou $ st $ l $ descriptionorganizationalUnitouuserPassword $ searchGuide $ seeAlso $ businessCategory $ *121Address $ registeredAddress $ destinationIndicator $ preferredDeliveryMethod $ tele*Number $ telete*TerminalIdentifier $ telephoneNumber $ internationaliSDNNumber $ facsimileTelephoneNumber $ street $ postOfficeBo* $ postalCode $ postalAddress $ physicalDeliveryOfficeName $ st $ l $ descriptionperson snuserPassword $ telephoneNumber $ seeAlso $ descriptionTop(所有类的基类)七、 常用目录效劳器1:Apache directory server2:Sun directory server 3:openDS 一个开源的,基于LDAP和DSML标准的Directory service。Directory service不仅包括Directory server,还有其它与directory相关的根本service:directory pro*y 、virtual dirctory、namespace distribution和数据同步Directory server是一个可以通过网络访问,信息分级存储的数据库。OpenDS只能用在linu*操作系统。该工程的地址为:.opends.org/4: Netscape Directory Server5: Window AD八、 Apache directory server安装与使用1:下载ApacheDS 地址为: 2:ApacheDS的安装比拟简单,没有什么特殊的设置。在ApacheDS 安装完成后要启动ApacheDS效劳。路径如下:控制面板-à 管理工具-à效劳-àApache Directory server ApacheDS的监听端口默认为10389 3:安装Apache directory studio。下载地址同上。该软件是ApacheDS的一个客户端工具。用于连接ApacheDS,搜索,更新,删除,添加数据。安装时也没有特别设置,请按默认设置安装该软件。 4:使用Apache directory studio连接ApacheDS 步骤如下:第一步:在菜单栏中选择LDAP菜单下的New Connection选项第二步:在下面的对话框中输入相应的值。第三步:在一下对话框中输入要连接的根DN和密码。在ApacheDS安装完成后,已经创立了几个DIT目录信息树,第一次登录ApacheDS的话一般会连接如下输入的根节点的DN 密码为:secret。当然可以在第一个选项框中选择No Authentication。这是不需要输入下面的验证信息。这种登录术语匿名登录。权限受限制。第四步。连接完成后,如下列图:图中出现了apahceDS安装默认创立的三个目录信息树第五步:创立Partition。ApacheDS中的目录信息是保存在Partition中的。所以在创立新的目录树之前首先要创立Partition。创立Partition的一个方法是修改server.*ml配置文件。该文件路径如下:C:Program FilesApache Directory Serverinstancesdefaultconf 在该文件中找到Partitions元素。添加<jdbmPartition>元素。第六步:创立完成之后,重启Apache direcory server 效劳。在Apache directory studio视图中看到结果如下,在右侧栏中我们可以看到我们刚刚添加的Partition。但是在左侧栏中,我们并没有看到该目录分支存在。因为,必须要创立一个Conte*t Entry。第七步:创立Conte*t Entry 12 3 4 5 6九、 LDAP应用场景使用JNDI操作目录效劳1. 准备连接目录效劳器的相应配置文件以ApacheDS为例apacheds.propertiesjava.naming.factory.initial=java.naming.provider.url=ldap:/localhost:10389/dc=e*ample,dc=java.naming.security.authentication=simplejava.naming.security.principal=uid=liujz,dc=e*ample,dc=s=1234562. 创立测试类public class LDAPTestprivate static DirConte*t ct*=null;privateProperties ldapProps;public LDAPTest(Properties ldapProp)This.ldapProp= ldapProp;public DirConte*t getDirConte*t()If(ct*=null)ct* = new InitialDirConte*t(ldapProps);return ct* ;/从LDAP效劳器中查询符合条件的Entrypublic void queryEntry()SearchControls sc = new SearchControls();/用于设置查询围/有三种查询围 SUBTREE_SCOPE:表示在以指定对象为根的子树中查找,可以返回多个元素ONLEVEL_SCOPE:表示指定对象极其直接子实体OBJECT_SCOPE:表示返回指定对象。sc.setSearchScope(SearchControls.SUBTREE_SCOPE); /该方法有单个参数,第一个参数是DN是一种相对的,因为根据配置文件,我们已经连接到根DN为dc=e*ample,dc=com的目录树上,所以一下方法查询的Entry的DN为 ou=Account,dc=e*ample,dc=。第二个参数是过滤器,相当于SQL中的where子句。第三个参数为查询控制String dn = “ou=Account; String filter = “ou=Account;NamingEnumeration result = getDirConte*t().search(dn,filter,sc);While(result.hasMore()SearchResult entry = (SearchResult)result.ne*t(); Attributes attrs = entry.getAttributes(); Attribute attr = attrs.get(“ou); System.out.println(“ou=+attr.get();/向LDAP效劳器中添加EntryPublicvoid addEntry() /在ou=account,dc=e*ample,dc=com节点下添加一个子节点。其RDN为cn=liujianzhong Attributes attrs = new BasicAttributes();attrs.put(“,liujianzhong); attrs.put(“sn,liu); attrs.put(“userpassword,123456); BasicAttribute objectClassSet = new BasicAtrribute(“objectclass);objectClassSet.add(“top): objectClassSet.add(“person); objectClassSet.add(“organizationalPerson); objectClassSet.add(“inetOrgPerson);attrs.put(objectClassSet);ct*.createSubConte*t(“=liujianzhong,ou=Account,attrs);/删除LDAP目录效劳器中指定的Entry,如果该节点为叶子节点则直接删除,否则要先得到该节点下的所有叶子节点,然后从最底层的叶子节点删除,直到删除所有叶子节点为止Publicvoid delEntry()/删除叶子节点 String DN = “=liujianzhong,ou=Account ;getDirConte*t().destroySubconte*t(DN); /删除非叶子节点String DN = “ou=Account,dc=e*ample,dc= ;/删除非叶子节点Publicvoid delDN(String dn,DirConte*t ct*)String root ="dc=e*ample,dc="SearchControls sc = new SearchControls();String filter = "(objectclass=*)"sc.setSearchScope(SearchControls.ONELEVEL_SCOPE);NamingEnumeration results = ct*.search(dn, filter, sc);while(results.hasMore()SearchResult entry = (SearchResult)results.ne*tElement();String name = entry.getNameInNamespace();int rin = name.length()-root.length()-1;String rdn = name.substring(0, rin);delDn(rdn,ct*);ct*.destroySubconte*t(dn);/修改LDAP效劳器中Entry的属性publicvoid modifyEntry(String dn,DirConte*t ct*)throws NamingE*ception BasicAttribute attr = new BasicAttribute("sn");attr.add("jianzhong"); /修改属性ModificationItem mods = new ModificationItem1;mods0 = new ModificationItem(LdapConte*t.REPLACE_ATTRIBUTE,attr);ct*.modifyAttributes(dn, mods);/添加属性BasicAttribute psw = new BasicAttribute(“userPassword);Psw.add(“123456);ModificationItem add=new ModificationItem1;Add0 = new ModificationItem(LdapConte*t.ADD_ATTRIBUTE,psw);ct*.modifyAttributes(dn, add);/删除属性BasicAttribute psw1= new BasicAttribute(“userPassword);ModificationItem rem=new ModificationItem1;Rem0 = new ModificationItem(LdapConte*t.ADD_ATTRIBUTE,psw1);ct*.modifyAttributes(dn, rem);. z.