首页 > 代码库 > LDAP协议介绍

LDAP协议介绍

LDAP协议基础概念 

1. 从用途上阐述LDAP,它是一个存储静态相关信息的服务,适合“一次记录多次读取”。经常使用LDAP服务存储的信息: 
  • 公司的物理设备信息(如打印机,它的IP地址、存放位置、厂商、购买时间等)
  •  公开的员工信息(地址、电话、电子邮件…)
  •  合同和账号信息(客户信息、产品交付日期、投标信息、项目信息…)
  •  凭证信息(认证凭证、许可证凭证…)

2. 从数据结构上阐述LDAP,它是一个树型结构,能有效明白的描写叙述一个组织结构特性的相关信息。在这个树型结构上的每一个节点,我们称之为“条目(Entry)”,每一个条目有自己的唯一可差别的名称(Distinguished Name ,DN)。条目的DN是由条目所在树型结构中的父节点位置(Base DN)和该条目的某个可用来差别身份的属性(称之为RDN如uid , cn)组合而成。对Full DN :“shineuserid=linly , ou=Employee , dc=jsoso , dc=net”而言,当中Base DN:“ou=Employee , dc=jsoso , dc=net”,RDN:“shineuserid=linly”以下是一个LDAPserver的数据结构图: 
 
3. 从协议衍化上阐述LDAP,它是“文件夹訪问协议DAP——ISO X.500”的衍生,简化了DAP协议,提供了轻量级的基于TCP/IP协议的网络訪问,减少了管理维护成本,但保持了强壮且易于扩充的信息框架。LDAP的应用程序能够非常轻松的新增、改动、查询和删除文件夹内容信息。 

LDAP文件夹条目(Directory Entry)简述 
从Object Classes谈起 
在LDAP文件夹数据库中,全部的条目都必须定义objectClass这个属性。这有点像Java语言里说阐述的“一切皆对象”的理念,每一个条目(LDAP Entry)都要定义自己的Object Classes。Object Class能够看作是LDAP Entry的模板,它定义了条目的属性集,包含必有属性(requited attribute)和可选属性(option attribute)。这里要着重指出的是,在LDAP的Entry中是不能像关系数据库的表那样随意加入属性字段的,一个Entry的属性是由它所继承的全部Object Classes的属性集合决定的,此外能够包含LDAP中规定的“操作属性”(操作属性是一种独立于Object Class而存在的属性,它能够赋给文件夹中的随意条目)。假设你想加入的属性不在Object Classes定义属性的范畴,也不是LDAP规定的操作属性,那么是不能直接绑定(在LDAP中,给Entry赋予属性的过程称为绑定)到条目上的,你必须自己定义一个含有你须要的属性的Object Class,而后将此类型赋给条目。 
Object Class是能够被继承的,这使它看上去真的非常像Java语言中的POJO对象。继承类的对象实例也必须实现父 
类规定的必有属性(requited attribute),同一时候拥有父类规定的可选属性(option attribute)。继承类能够扩展父类的必有属性和可选属性。因为Object Class的继承特性,因此在一个LDAP Entry上,objectClass属性是一个多值属性,它涵盖了Object Class的完整继承树,如用户条目uid=Linly , ou=People, dc=jsoso , dc=net,它直接实现了inetorgperson这个对象类,那么它的objectClass属性值为inetorgperson,organizationalPerson,person,top。 

从Object Classes到Directory Server Schema 
上一章节中,我们了解了LDAP条目都要遵守的一个最重要的规定Object Classes,而实际上,对Entry很多其它更细的规范被涵盖在了Directory Server Schema(文件夹服务模式)中。Directory Schema声明了完整的LDAP数据的存储规范,这包含数据的字节大小、数值范围和格式定义。 
默认的,在一个LDAPserver上,都定义有一套标准的Schema和一套为server功能定制的Schema。用户在须要的时候,是能够定制自己的LDAP属性和Object Class,以扩展标准Schema的功能。在Sun Directory Server中,使用了标准LDAPv3 Schema,并在此基础上做了轻微的扩展。 

在Schema中的标准属性(Standard Attributes)是一个键-值对,如:cn:linly ,属性ID(属性名)为cn,属性值为linly 。其实,一个完整的条目就是由一系列的键-值对组成的。下面是一个完整的LDAP Entry: 
引用
dn: uid=Linly,ou=People, dc=jsoso,dc=net 
telephoneNumber: 13950491407 
mail: linliangyi2005@gmail.com 
objectClass: top 
objectClass: person 
objectClass: organizationalPerson 
objectClass: inetorgperson 
cn: LinLiangyi 
userPassword: {SSHA}aPTgP47LeziVGqjPBI8343FwkcL3QgQQ9kirXw== 
creatorsName: uid=admin,ou=administrators,ou=topologymanagement,o=netscaperoot 
createTimestamp: 20080219070003Z 
nsUniqueId: 2deb0d01-deb811dc-8055dc88-5f880db9 
nsRoleDN: cn=MyAdminRole,ou=People,dc=jsoso,dc=net 
nsRoleDN: cn=secondRole,ou=People,dc=jsoso,dc=net 
cn;phonetic;lang-zh:: IA== 
preferredLanguage: zh-CN 
cn;lang-zh:: 5p6X6Imv55uKICA= 
givenName: liangyi 
givenName;lang-zh:: 6Imv55uK 
sn: lin 
sn;lang-zh:: 5p6X 
uid: linly 
manager: cosTemplateForPostalCode 
modifiersName: uid=admin,ou=administrators,ou=topologymanagement,o=netscaperoot 
modifyTimestamp: 20080227083015Z


在Schema中,对属性的定义包括下面内容: 
  •  一个唯一的属性名称
  •  一个属性的OID(object  identifier)
  •  一段属性的文本描写叙述信息
  •  一个关联属性文法定义的OID
  •  属性的单值/多值描写叙述;属性是否是文件夹自有的;属性的由来;附加的一些匹配规则


此外Schema中最重要的部分就是我们上面提到的Object Classes,它实际上是提前定义的一套捆绑成套的属性集合。在Schema定义中,Object Classes要包括下面内容: 
  •  一个唯一的名字
  •  一个object identifier (OID) 定义Object Class
  •  一个必有的属性集合
  •  一个可选的属性集合


高级LDAP条目 
在文件夹服务中,信息是以条目的形式被分层次的组织在一起的。LDAP提供了几种分组机制,使得信息管理更富有弹性。 

静态组和动态组(Static Group and Dynamic Group) 
组(Group),声明一个文件夹条目的集合 
静态组(Static Group):显式声明了一个它的集合成员,这样的方式适用于少量明白的成员组合。 
动态组(Dynamic Group):它定义了一个过滤条件,全部匹配条件的条目都是组的成员。所以称之为动态组,是由于每次读取其组员名单时,要动态计算过滤条件。 
使用组的长处是可以高速的查找所属的成员;缺点是,给出随意的成员,无法获知它所属的组。因此从数据关联关系上看,Group适合一对多的查询。 

受管角色、过滤器角色和嵌套角色(Managed Role、Filtered Role and Nested Role) 
角色(Role),它是条目的还有一种集合形式。它与组不同的在于,给定一个随意的成员条目,我们能立马获知它所属的角色。因此从数据关联关系上看,Role适合多对一的查询。角色定义仅对它们的父节点子树以下的文件夹条目有效。 
受管角色(Managed Role),它等价于Group中的静态组,不同的是,Role不是把组员信息加入到自身属性中,而是将自身的DN加入到组员条目的nsroledn属性中。 
过滤器角色(Filtered Role),它与动态组相似,通过定义条目过滤器来确定组员。 
嵌套角色(Nested Role),它是对角色定义的一种嵌套形式。能够嵌套其他的嵌套角色的。嵌套角色的成员,是其包括的全部角色成员的合集。嵌套角色通过包括从属于其他子树下的角色,能够扩展其搜索的scope。 

服务类CoS 
服务类实际上是一种属性的共享机制,它无须定义条目间的关联关系,却能够做到数据同步和空间优化。比如,在一个公司文件夹下,拥有上千个员工,他们拥有同样的公司地址属性;在传统的条目中,地址属性分别存贮在员工条目里,这样不但浪费存储空间,一旦地址变更,则要对员工条目进行逐一改动。採用CoS机制后,公司地址属性被存放在一个对象内,员工条目通过引用这个对象来获得地址信息,从而缩小的存储空间损耗,并方便了信息的改动。 
CoS仅对其父节点子树以下的文件夹条目有效。CoS机制包括两个部分,CoS 定义条目和CoS模板条目。定义条目描写叙述了属性是怎样被引用的;模板条目描写叙述了属性的值。CoS机制包括3种类型: 
指针服务类(Pointer CoS), 
在Pointer CoS中,CoS包括一个定义Definition Entry,它指定了两个属性:1.共享属性的名称;2.提供共享数据的模板DN。 另外CoS还要有一个Template Entry,它要提供共享的数据。 
在定义了Definition Entry和Template Entry后,Pointer CoS将为其父节点子树以下的全部条目(目标条目Target Entry)分配共享属性和模板所定义的值。示意图例如以下: 
 
 Definition Entry:cn=PointerCoS , dc=example , dc= com定义了CoS的共享属性cosAttribute:postalCode,同一时候定义了CoS的模板DN cosTemplateDN:cn=cosTemplateForPostalCode,cn=data。 
 Template Entry: 它是CoS的模板,定义了共享属性值 postalCode:45773。 
 Target Entry:它是目标条目,由于它位于dc=example , dc=com的子树下。所以它获得了共享属性postalCode:45773。 

间接服务类(Indirect CoS)
在使用间接服务类时,在Definition Entry条目中定义了CoS的共享属性cosAttribut和一个用来间接指向模板的属性cosIndirectSpecifier。 
首先,我们须要用cosIndirectSpecifier的值A作为属性名,来检索CoS父节点子树中全部拥有A属性的条目,作为目标条目Target Entry。 
其次,依据找到的Target Entry条目中A属性的值来定位模板对象。 
最后,再分别依据找到的模板对象中拥有的共享属性值赋给相应的Target Entry。 
比如,定义例如以下Definition Entry
引用
dn: cn=generateDeptNum,ou=People,dc=example,dc=com 
objectclass: top 
objectclass: LDAPsubentry 
objectclass: cosSuperDefinition 
objectclass: cosIndirectDefinition 
cosIndirectSpecifier: manager 
cosAttribute: departmentNumber

该CoS定义对条目ou=People,dc=example,dc=com下的子树中全部具有manager属性的 条目有效,同一时候设定其CoS模板指向manager属性的值所指向的条目。 
又假定有例如以下的Template Entry条目,它具有属性departmentNumber: 
引用
dn: cn=Carla Fuentes,ou=People,dc=example,dc=com 
… 
objectclass: cosTemplate 
… 
departmentNumber: 318842

同一时候在ou=People,dc=example,dc=com下有Target Entry例如以下: 
引用
dn: cn=Babs Jensen,ou=People,dc=example,dc=com 
cn: Babs Jensen 
... 
manager: cn=Carla Fuentes,ou=People,dc=example,dc=com 
departmentNumber: 318842

由于该Entry具有manager属性,且在ou=People,dc=example,dc=com子树下,所以它成为了Target Entity。而且由于其manager的值指向模板cn=Carla Fuentes,ou=People,dc=example,dc=com,因此,它的departmentNumber为 318842。 

经典服务类(Classic CoS) 
经典服务类同间接服务类有点相似,它也是对属性的间接应用。在Classic CoS的定义条目中,除了共享属性定义外,还有两个定义,一个是cosTemplateDn,它指向模板条目的父节点;还有一个是cosSpecifier,它的值指向目标条目的属性A。由目标条目的属性A的值来取代模板条目的RND。则目标条目的属性A的值加上cosTemplateDn的值恰好定义一个唯一的模板条目。 
举比例如以下,首先是一个经典服务类的定义条目: 
引用
dn: cn=classicCoS,dc=example,dc=com 
objectclass: top 
objectclass: LDAPsubentry 
objectclass: cosSuperDefinition 
objectclass: cosClassicDefinition 
cosTemplateDn: ou=People,dc=example,dc=com 
cosSpecifier: building 
cosAttribute: postalAddress

该定义条目指明了3个參数, 
1. 要共享的属性是postalAddress 
2. 模板条目的上下文前缀是ou=People,dc=example,dc=com 
3. 模板条目的RDN存储于目标条目的building属性中 
其次,假定有例如以下模板条目: 
引用
dn: cn=B07,ou=People,dc=example,dc=com 
objectclass: top 
objectclass: LDAPsubentry 
objectclass: extensibleobject 
objectclass: cosTemplate 
postalAddres: 7 Old Oak Street$Anytown, CA 95054

最后,我们如果有下面目标条目: 
引用
dn: cn=Babs Jensen,ou=People,dc=example,dc=com 
cn: Babs Jensen 
... 
building: B07 
postalAddres: 7 Old Oak Street$Anytown, CA 95054

因为目标条目中,building属性的值是B07,因此该条目的模板定义DN = B07加上ou=People,dc=example,dc=com ,即cn=B07,ou=People,dc=example,dc=com,因此目标条目的postalAddres 引用模板的值7 Old Oak Street$Anytown, CA 95054。

LDAP 文件夹搜索 
LDAP搜索是文件夹服务最经常使用的功能之中的一个。在LDAP服务中搜索要用到对应的Filter语句。Filter语句由3个部分组成: 
1. 属性,如:cn ,uid ,操作属性如:objectClass  ,  nsroledn 
2. 比較操作符 ,如 < , > ,= ,… 
3. 逻辑预算符,如: 与操作&  , 或操作| , 非操作! 
关于Filter语句组成的具体參数表例如以下: 
filter的运算符 
 
filter布尔运算符 
 

搜索过滤器演示样例 
  • 下列过滤器将搜索包括一个或多个 manager 属性值的条目。这也称为存在搜索:manager=*
  • 下列过滤器将搜索包括通用名 Ray Kultgen 的条目。这也称为等价搜索:cn=Ray Kultgen
  • 下列过滤器返回全部不包括通用名 Ray Kultgen 的条目:(!(cn=Ray Kultgen))
  • 下列过滤器返回的全部条目中都有包括子字符串 X.500 的说明属性:description=*X.500*
  • 下列过滤器返回全部组织单元为 Marketing 且说明字段中不包括子字符串 X.500 的条目:(&(ou=Marketing)(!(description=*X.500*)))
  • 下列过滤器返回全部组织单元为 Marketing 且 manager 为 Julie Fulmer 或 Cindy Zwaska 的条目:(&(ou=Marketing)(|(manager=cn=Julie Fulmer,ou=Marketing,dc=siroe,dc=com)(manager=cn=Cindy Zwaska,ou=Marketing,dc=siroe,dc=com)))
  • 下列过滤器返回全部不代表人员的条目:(!(objectClass=person))
  • 下列过滤器返回全部不代表人员且通用名近似于 printer3b 的条目:(&(!(objectClass=person))(cn~=printer3b))


ldapsearch指令參数-b 搜索的起始上下文 
  • -D 绑定搜索的账号Distinguished Name
  • -h 主机名。地址
  • -p LDAP服务port
  • -l 搜索的最大耗时
  • -s 从上下文開始的搜索范围,有三个常量base(表示仅当前根对象)/one(当前根对象及下一级)/sub(当前根对象的所有子树)
  • -W 绑定账号password
  • -z 返回结果的最大数量


搜索“操作属性” 
在LDAP搜索中,操作属性在默认情况下是不会尾随搜索结果返回的。必须在搜索中明白显示的指定操作属性,如: 
引用
ldapsearch -h linly.jsoso.net -p 5201 -D "cn=directory manager" -w password "objectclass=*" aci=accounts。


搜索“操作对象类”的条目 
在LDAP中Role、CoS等对象被定义为特殊的Object Class——操作对象类(operational object class),在一般的搜索中,这类对象是不会作为结果返回给用户的。要想查找这些对象,必须在filter中显式定义要找这个对象类。比如:(objectclass=ldapsubentry)。 

ACI权限控制 
ACI(Access Control Instruction)訪问控制指令是LDAP 服务中用以控制用户訪问权限的有力手段。在文件夹的Entry中,aci属性记录了对该条目的多条訪问控制指令。(aci属性是一个多值操作属性,能够赋予随意的LDAP条目) 
ACI的语法格式例如以下:aci: (target)(version 3.0;acl "name";permission bind_rules;) 
target 指定了ACI要控制訪问的目标属性(集合)或条目(集合)。target能够用DN,一个或多个属性,或者一个filter来定义。它是一个可选项。 
target语法是:keyword <op> 表达式 
targetkeyword表 
 
(很多其它具体的target使用方法,请參阅 Sun ONE Directory Server 5.2 Administration Guide ) 

version 3.0 这是一个必须的常量字窜,用以识别ACI的版本号。 

name 指定ACI的名称,能够使随意的字窜,仅仅要差别于同一个条目aci属性下的其它ACI,这是一个必须属性。 

permission 指定权限许可。 
权限包含:read、write、add、delete、search、compare、selfwrite、 proxy 或 all,当中all表示出了proxy之外的全部操作。 
权限语法:allow | deny (权限) 

bind_rules 绑定规则。绑定规则定义了何人、何时,以及从何处能够訪问文件夹。绑定规则能够是例如以下规则之中的一个: 
  • ? 被授予訪问权限的用户、组以及角色
  • ? 实体必须从中绑定的位置
  • ? 绑定必须发生的时间或日期
  • ? 绑定期间必须使用的验证类型

绑定规则语法:keyword  = 或者 != "expression"; (注:timeofday keyword也支持不等式<、<=、>、>=)。 
LDIF 绑定规则keyword表 
 

(很多其它具体的绑定规则使用方法,请參阅 Sun ONE Directory Server 5.2 Administration Guide ) 

ACI例子 
  • 1.用户 bjensen 具有改动其自己的文件夹条目中全部属性的权限。aci:(target="ldap:///uid=bjensen,dc=example,dc=com")(targetattr=*)(version 3.0; acl "aci1"; allow (write) userdn="ldap:///self";)
  • 2.同意 Engineering Admins 组的成员改动 Engineering 业务类别中全部条目的 departmentNumber 和 manager 属性aci:(targetattr="departmentNumber || manager")(targetfilter="(businessCategory=Engineering)") (version 3.0; acl "eng-admins-write"; allow (write) groupdn ="ldap:///cn=Engineering Admins, dc=example,dc=com";)
  • 3.同意匿名用户对o=NetscapeRoot下的条目读取和搜索aci:(targetattr="*")(targetfilter=(o=NetscapeRoot))(version 3.0; acl "Default anonymous access"; allow (read, search) userdn="ldap:///anyone";)
  • 4.向全部经过验证的用户授予对整个树的读取訪问,能够在dc=example,dc=com 节点创建下列 ACI:aci:(version 3.0; acl "all-read"; allow (read)userdn="ldap:///all";)
  • 5.同意对整个 example.com 树进行匿名读取和搜索訪问,能够在dc=example,dc=com 节点创建下列 ACI:aci:(version 3.0; acl "anonymous-read-search";allow (read, search) userdn = "ldap:///anyone";)
  • 授予Administrators 组对整个文件夹树写入的权限,则能够在 dc=example,dc=com 节点创建下列 ACI:aci:(version 3.0; acl "Administrators-write"; allow (write) groupdn="ldap:///cn=Administrators,dc=example,dc=com";)