了解LDAP协议、数据结构与条目组件

提供:ZStack云计算

内容介绍

LDAP, 全称为轻量级目录访问协议,是一项开放协议,用于通过分层目录结构对数据进行存储与检索。LDAP是一种灵活的解决方案,适用于定义各类条目及相关性质。

对大多数用户而言,LDAP似乎难于理解——因为其使用专项术语,采用多种不太常见的缩写,且常常作为大型组件交互系统中的组成部分使用。在本教程中,我们将介绍LDAP基础概念,帮助大家顺利上手这套方案。

目录服务是什么?

目录服务用于通过键-值类型格式存储、整理及表达数据。一般来讲,目录会面向查找、搜索以及读取操作做出优化,因此适用于经常引用但却较少变更的数据。

存储在目录服务中的数据通常根据特性加以描述,并用于定义某条目的性质。以通讯簿为例,每个人都能够以一个条目的方式在目录中表现,由键-值对描述其通讯信息、业务范围等。目录服务适用于各类需要进行定性的描述性信息。

LDAP是什么?

LDAP,全称为轻量级目录访问协议,是一项用于定义目录服务访问方法的通信协议。总体来讲,LDAP能够定义数据在目录服务内如何呈现给用户,定义目录服务内各用于创建数据条目的组件,同时概述组成条目的不同基本元素。

由于LDAP是一项开放协议,因此其拥有多种实现方式。OpenLDAP项目正是其中广受支持的开源衍生成果。

基本LDAP数据组件

LDAP向用户显示数据的方式多种多样,具体取决于所定义结构组件之间的交互与关系,因此其复杂程度相当之高。

属性

LDAP系统中的数据主要以被称为属性的元素形式存储。属性在本质上属于键-值对。与其它系统不同,其中的键名称由为条目选定的objectClasses进行预定义。另外,属性中的数据必须匹配属性初始定义内所定义的类型。

要为属性设定值,我们需要为其提供属性名称与属性值,二者以逗号加一个空格隔开。以下示例为名为mail且负责定义邮箱地址的属性:

mail: [email protected]

在引用属性及其数据(非设定时)时,注意使用等号:

mail=example.com

该属性值包含我们需要在LDAP系统中存储并访问的大部分实际数据。LDAP中的其它元素则用于表达结构与组织等等。

条目

单凭属性本身没有多少作用,我们必须将其与其它事物进行关联。在LDAP中,我们在条目内使用属性。条目基本上相当于属性与一条用于描述事物的名称的集合。

例如,大家可以在系统为一位用户设置一个条目,或者在库存目录中为每项目设置条目。这类似于关系数据库系统中的一行或者通讯簿中的一页。属性定义的是一条性质或者特征,而条目则通过属性于名称的结合描述项目本身。

LDIF(即LDAP数据交换格式)内的条目示例如下:

dn: sn=Ellingwood,ou=people,dc=digitalocean,dc=com
objectclass: person
sn: Ellingwood
cn: Justin Ellingwood

以上即为LDAP系统中的一条有效条目。

DIT

熟悉了LDAP之后,大家会发现属性所定义的数据只代表某一对象的一部分可用信息。其余部分则存在于LDAP当中,即其相互关系。

例如,如果我们可以为一个用户与一个库存项目设置条目,那么人们该如何对二者加以区分?一种方式就是建立关系与组。条目在创建之时即拥有这一功能,而条目则会被添加至LDAP系统当中充当分支或者树,即数据信息树,简称DIT。

DIT代表的是与文件系统类似的一种组织化结构,其中每个条目(除了顶级条目)有且只有一个父条目,其下则可能拥有任意数量子条目。因此,LDAP树内的各条目可以代表任何事物,其中部分条目将被主要用于组织用途,类似于文件系统内的目录。

如此一来,大家就能够为“人员”创建一个条目,再为“库存项目”创建一个条目。大家的实际数据条目可以作为二者之下的子条目存在。另外,各组织型条目可以随意定义为最理想的数据代表方式。

在上一章节的示例条目,我们可以看到dn行中的DIT表现:

dn: sn=Ellingwood,ou=people,dc=digitalocean,dc=com

此行被称为该条目的专有名称,用于指定条目身份。其作用类似于指向DIT root的完整路径。在本示例中,我们的条目名为sn=Ellingwood,而其直接父条目则为ou=people,其可能用于容纳负责描述人员的各相关条目此条目的各父条目衍生自digitalocean.com域名,其作为我们DIT的root存在。

定义LDAP数据组件

在上一节,我们探讨了数据如何在LDAP系统中加以表现。然而,我们还需要讨论负责存储数据的各组件的定义方式。例如,我们提到数据必须与每条属性的定义类型相匹配。这些定义来自哪里?下面我们从底层开始,一步步加以讲解。

属性定义

属性利用相当复杂的语法进行定义。其必须注明属性名称、任何其它能够用于引用该属性的名称、可以输入的数据类型以及其它各类元数据。该元数据能够描述此属性,告知LDAP如何对属性值进行排序或比对,同时告知其如何将其与其它属性相关联。

例如,以下为name属性的定义:

attributetype ( 2.5.4.41 NAME 'name' DESC 'RFC4519: common supertype of name attributes'
    EQUALITY caseIgnoreMatch
    SUBSTR caseIgnoreSubstringsMatch
    SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} )

其中“name”为属性的名称。第一行中的数字为全局惟一OID(即对象ID),被分配至该属性以将其同其它属性区分开来。条目中的其它内容则定义该条目在搜索中如何实现比对,另有一个指针告知属性的数据类型要求应在哪里找到信息。

属性定义中的一大要点在于,该属性是否能够在条目中进行多次定义。例如,定义可能要求每个姓氏只能在各条目中被定义一次,但“侄女”的属性则允许该属性在单一条目中被定义多次。属性在默认情况下可包含多个值,且如果在单一条目中只能被定义一次,则必须以SINGLE-VALUE加以标记。

属性定义要比属性的使用与设定更为复杂。幸运的是,大多数情况下我们无需自行定义属性,因为大部分LDAP实现方案中已经提供各类最为常用的属性,其它方案亦能够轻松导入现成属性。

ObjectClass定义

各属性被收集在objectClasses条目当中。ObjectClasses属于相关属性的简单分组,可用于描述特定事物。例如,“个人”就属于一个objectClass。

条目能够通过设置一条objectClass特殊属性的方式使用objectClass的属性,当然大家也可以使用任何其它objectClass。事实上,objectClass是我们在条目中无需进一步指定objectClass即能够设置的惟一属性。

因此,如果大家打算创建一个条目以描述某个人,那么添加objectClass person(或者任何特定个人)即可使用该objectClss中的全部属性:

dn: . . .
objectClass: person

大家可以在该条目中设定以下属性:

  • cn: 通用名称
  • description: 人类可阅读的条目描述
  • seeAlso: 引用相关条目
  • sn: 姓氏
  • telephoneNumber: 一条电话号码
  • userPassword: 一条用户密码

如果大家需要使用来自其它objectClasses的属性,则可多次使用objectClass属性,但需要遵循相关接纳规则。ObjectClasses被定义为多种“类型”之一。

ObjectClasses的两大主要类型为结构型与辅助型。单一条目必须拥有单一结构类,但可能不具备或者具备多个结构类(用于为该类提供可用属性)。结构型objectClass则用于创建及定义该条目,而辅助型objectClasses则通过额外添加为其提供附加功能。

ObjectClass定义会检测其提供的各属性是否必要(由MUST规范指示)或者属于可靠锭(由MAY规范指示)。多个objectClasses能够提供同样的属性,而单一属性的MAY或者MUST分类可能在不同objectClasses之间有所区别。

例如,person objectClass定义如下:

objectclass ( 2.5.6.6 NAME 'person' DESC 'RFC2256: a person' SUP top STRUCTURAL
  MUST ( sn $ cn )
  MAY ( userPassword $ telephoneNumber $ seeAlso $ description ) )

其被定义为一个结构型objectClass,意味着其可用于创建一个条目。此创建的条目必须设定surname与commonname属性,且可选设定userPassword、telephoneNumber、seeAlso或者description属性。

Schemas

ObjectClass定义与属性定义二者由一套架构组合在一起,这就是schema。与传统关系数据库不同,LDAP中的schemas单纯收集相关objectClasses与属性。单一DIT能够包含多个不同schemas,因此其可以创建需要的条目与属性。

Schemas通常包含额外的属性定义且可能要求该属性在其它schemas中定义。例如,我们之前提到的person objectClass就要求利用person objectClass为任意条目设定surname或者snattribute。如果其在LDAP服务器内部未经定义,则包含有这些定义的schema可用于将这些定义添加至服务器词汇。

Schema格式基本上属于以上条目的结合,例如:

. . .

objectclass ( 2.5.6.6 NAME 'person' DESC 'RFC2256: a person' SUP top STRUCTURAL
  MUST ( sn $ cn )
  MAY ( userPassword $ telephoneNumber $ seeAlso $ description ) )

attributetype ( 2.5.4.4 NAME ( 'sn' 'surname' )
  DESC 'RFC2256: last (family) name(s) for which the entity is known by' SUP name )

attributetype ( 2.5.4.4 NAME ( 'cn' 'commonName' )
  DESC 'RFC4519: common name(s) for which the entity is known by' SUP name )

. . .

数据组织

我们已经探讨了LDAP系统内用于构建条目的常见元素,亦谈到了这些组成部分如何在系统中进行定义。然而,我们还没有提到信息自身如何组织并在LDAP DIT中建立结构。

在DIT中安置条目

一条DIT单纯属于描述现有条目间关系的层次结构。在创建之后,每个新条目都必须“钩入”现有DIT,即将自身作为现有条目的一个子条目。这会建立起一套树状结构,用于定义关系并分配含义。

DIT的顶端为最广泛的范畴,其下则属于某种方式的后代。通常情况下,顶端条目作为标签指明DIT所使用的组织。这些条目可以根据objectClasses的需要进行任意调整,但一般其会利用哉组件(与example.com的LDAP管理信息相关的为dc=example,dc=com)、位置(位于纽约的组织或者分区为l=new_york,c=us)或者组织型分区(ou=mrketing,o=Example_Co)进行构建。

组织所使用的条目(使用方式与文件夹类似)通常使用组织型Unit objectClass,其允许使用名为ou=的简单描述性属性标签。其通常用于顶端DIT条目(例如ou=people,ou=groups以及ou=inventory)的常规分类。LDAP专门针对遵循树状结构进行信息查找做出优化,因此往往最适合保留DIT结构,其中通过特定属性分配表明其进一步细分方式。

在DIT内命名并引用条目

我们根据属性进行条目引用。这意味着每个条目必须拥有一条或者一组属性,其在DIT层次中拥有明确的等级。此属性或者属性组被称为该条目的相对可分辨名称,或者简称RDN,其功能与文件名称类似。

要明确引用栽个条目,大家可以使用该条目的RDN同时结合其父条目的全部RDN。这条RDN锭会逐步引导回DIT层次顶端,并为查询的条目提供一条明确路径。我们将这条RDN链称为条目的专有名称,或者简称DN。大家必须在创建过程中为条目指定该DN,这样LDAP系统才能知晓在哪里安置新条目,同时确保该条目的RDN不会为其它现有条目所使用。

打个比方,大家可以将RDN看作是文件或者目录名。另一方面,DN则更像是路径。不过一大重要区别在于,LDAP DN将大部分特定值容纳在左侧,而文件路径则将大部分特定信息容纳于右侧。DN将RDN各值以逗号分隔。

例如,一个面向John Smith的条目可能被放置于“人员”条目之下,后者则充当example.com的组织。由于该组织内可能存在多位John Smiths,因此我们最好使用用户ID作为该条目的RDN。该条目如下所示:

dn: uid=jsmith1,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: John Smith
sn: Smith
uid: jsmith1

我们需要使用inetOrgPerson objectClass以访问此实例中的uid属性(我们也拥有该person objectClass内所定义的全部属性的访问能力,接下来将进一步说明)。

LDAP继承

在实际应用当中,LDAP系统中的大多数数据彼此关联为层次、继承与嵌套。LDAP之所以不为大家所熟悉,很大程度上是因为其在设计中采用了部分面向对象概念。这一点主要体现在类的使用方面,外加层次的存在——而这正是本部分的核心内容。

ObjectClass继承

每个objectClass都是一个类,负责描述该类型对象的特征。

不过与简单的层次机制不同,LDAP中的对象能够且通常为多个类实例(部分编程语言利用多层次提供类似的功能)。这是因为LDAP的类概念单纯只是一个其MUST或者MAY具备的属性的集合。这意味着单一条目能够拥有多个类(尽管其中只有一个结构型objectClass能够且必须得以表达),结果就是该对象中利用严格的MUST或者MAY声明对合并后的属性集合加以访问。

在定义当中,objectClass能够指定一个父objectClass,并经由后者继承其属性。具体用法为在objectClass后面使用SUP来指定继承自何处。例如,organizationalPerson objectClass为:

objectclass ( 2.5.6.7 NAME 'organizationalPerson' SUP person STRUCTURAL
 . . .

该objectClass后的SUP标识符指明其父objectClass。该父类必须共享该objectClass所定义的objectClass类型(例如结构型或者辅助型)。子objectClass会自动继承该父类的属性与属性要求。

在条目中分配objectClass时,大家只需要为某继承链中最为具体的后代指定为可访问全部上层属性即可。在上一节中,我们利用这种方式将inetOrgPerson作为惟一objectClass指定至我们的John Smith条目,但同时仍保留了person与organizationlPerson objectClasses中所定义属性的访问能力。其中inetOrgPerson继承层次如下所示:

inetOrgPerson -> organizationalPerson -> person -> top

几乎全部objectClass继承树都会以名为“top”的特殊objectClass作为结尾。这是一个抽象objectClass,其惟一作用就是要求objectClass自身处于设置完成状态。它用于指定该继承链的顶部。

属性继承

属性也能够在定义过程中以类似的方式列举一项父属性。该属性随后将继承父属性中所设置的各项属性。

其通常用于为某项通用属性生成更为具体的版本。例如,surname为一种名称类型,且可使用与相同的方法实现特性比对与检查。它能够继承这些特性以获得“name”属性的通用形式。事实上,具体surname定义可能仅包含一个回指至父属性的指针。

通过这种方式,我们能够创建一条特定属性,从而帮助人们解释该元素,且其通用形式仍然不受影响。我们在这里谈到的surname属性,其继承机制就能帮助人员区分姓氏与普通姓名,但除了值的含义不同之外,姓氏与名称对于LDAP系统而言几乎没有区别。

LDAP协议的衍生版本

我们在文章开头提到,LDAP代表的是一套定义通信接口以实现目录服务协作的协议。我们通常将其称为LDAP或者ldap协议。

不过需要强调的是,在常规形式之外其还拥有多个衍生版本:

  • ldap://: 一项基本LDAP协议,允许对目录服务进行结构化访问。
  • ldaps://: 此衍生版本用于通过SSL/TLS实现LDAP表达。普通LDAP流量未经加密,不过大多数LDAP实现方案支持此功能。这种LDAP连接加密方法实际已经被弃用,建议大家使用STARTTLS作为替代。如果大家在非安全网络上使用LDAP,则强烈建议使用加密机制。
  • ldapi://: 用于通过IPC表达LDAP。其通常用于安全接入本地LDAP系统以实现管理用途。其能够内部嵌套而非公开网络端口实现通信。

这三种格式皆使用LDAP协议,但后两种使用额外专有信息指定其使用方式。

总结

到这里,大家应该已经理解了LDAP协议以及如何利用LDAP向用户表达数据。另外,我们也探讨了该系统中的各元素如何彼此关联,其在哪里实现属性管理以及怎样以更轻松且更具预测性的方式使用LDAP系统。

本文来源自DigitalOcean Community。英文原文:Understanding the LDAP Protocol, Data Hierarchy, and Entry Components By Justin Ellingwood

翻译:diradw

你可能感兴趣的:(了解LDAP协议、数据结构与条目组件)