轻量级目录访问协议 LDAP( Lightweight Directory Access Protocol ),是目录访问协议(DAP) 的“轻量级”版本,它是 X.500( 网络中目录服务的标准 )的一部分。由于 X.500 的实施太过于复杂而受到批评,为解决这个问题,密歇根州(Michigan)大学推出了一种较为简单的基于TCP/IP的DAP 新版本,即轻量级目录访问协议LDAP,主要用于因特网,LDAP 已迅速发展成为因特网上事实的目录协议标准。而在企业中通常都会自建一套LDAP服务,用于保存员工信息和组织架构,同时可以作为个人电脑以及应用系统(办公系统、Gitlab、Jira、Redmine等)的统一认证和登录。
一个标准的LDAP目录系统,主要包括以下几部分:
LDAP目录以树状的层次结构来存储数据,目录是一个为查询、浏览和搜索而优化的专业分布式数据库,它呈树状结构组织数据。目录数据库和关系数据库不同,它有优异的读性能,但写性能差,并且没有事务处理、回滚等复杂功能,不适于存储修改频繁的数据。
这里列出LDAP常见的缩写:
LDAP存储的数据呈现层级树状结构,即对应目录信息树DIT,而树状结构中的每一个节点被称为条目Entry,这些条目一般代表一个真实世界的条目,比如组织、用户等等,可类比关系型数据库中的一条记录,同时这些条目Entry的层次也可以和数据包含关系进行对应,例如域名->子公司->部门->用户。通常对LDAP的添加、删除、更改、检索都是以条目为基本对象的。
如下图即表示一个目录信息树DIT的树形结构,图中的蓝框即表示组成DIT的各个条目Entry:
 
Base DN:LDAP目录树的最顶部就是根,如上图中的根节点dc=mydomain,dc=com。
DN(Distinguished Name):每一个条目Entry都有一个唯一的标识名即DN,如上图中cn=luohq条目即对应DN:
 cn=luohq,ou=technology,ou=people,dc=mydomain,dc=com。
 通过DN的层次型语法结构,可以方便地表示出条目在LDAP树中的位置,通常用于检索。
RDN(Relative Distinguished Name):相对唯一名称,指DIT内某个节点上的名称,上层节点的DN配合上本节点的RDN,能够构成本节点的DN,如ou=people条目的RDN:ou=people,配合其上层条目的DN:dc=mydomain,dc=com即组成ou=people条目的DN:ou=people,dc=mydomain,dc=com。
Root DN:特指管理LDAP中信息的最高权限用户。
具体到一个条目Entry是由属性Attribue及属性值构成:

属性不是随便定义的,需要符合一定的规则,而这个规则可以通过模式Schema制定。条目数据在导入时通常需要接受模式Schema检查,它确保了目录中所有的条目数据结构都是一致的。
 模式Schema规定了:
按照面向对象思维,可以将ObjectClass理解为为类定义、AttributeType是属性定义、Syntax则是属性值的类型。且ObjectClass间支持继承,同时每个条目Entry可以直接继承多个对象类ObjectClass,这样就继承了各种属性。
LDAP预想了很多人员组织机构中常见的对象,并将其封装成对象类,常见的对象类ObjectClass如下:
对象类本身是可以相互继承的,所以对象类的根类是top抽象型对象类。
| 对象类ObjectClass | 说明 | 父类 | 必包含属性 | 可选包含属性 | 
|---|---|---|---|---|
| country | 国家 | top | c | searchGuide\description | 
| dcObject | 域名对象 | top | dc | - | 
| device | 设备 | top | cn | serialNumber\seeAlso\owner\ou\o\l\description | 
| organization | 组织 | top | o | userPassword\searchGuide…超多 | 
| person | 个人 | top | sn\cn | userPassword elephoneNumber\seeAlso\description | 
常见的属性类型AttributeType如下:
| 属性类型AttributeType | 说明 | 父类 | 语法 | 匹配方式 | 
|---|---|---|---|---|
| name | 名字, 是所有名字类种类的父类  | - | Directory String | caseIgnoreMatch | 
| c | country name,国家名 | name | Country String | |
| st | state or province name,州或省 | name | 同name | 同name | 
| l | locality name,地点名 | name | 同name | 同name | 
| dc | domain component,域名组件即域名的一部分, 比如mydomain.com由dc=mydomain,dc=com两个dc组成  | - | IA5 String | caseIgnoreIA5Match | 
| o | orgnazation name,机构名 | name | 同name | 同name | 
| ou | orgnazation unit name,机构单位名 | name | 同name | 同name | 
| cn | common name,通用名字 | name | 同name | 同name | 
| sn | surname,姓 | name | 同name | 同name | 
| uid | user id,用户唯一标识 | - | Directory String | caseIgnoreMatch | 
| userPassword | 用户密码 | - | Octet String | octetStringMatch | 
常见的语法Syntax如下:
| 语法Syntax | 举例 | 
|---|---|
| Bit String | ’0101111101’B | 
| Boolean | TRUE/FALSE | 
| Country String | UA、AU:两个可打印字符 | 
| Directory String | This is a value of Directory String containing:UTF8字符串 | 
| DN | CN=John Smith, III,DC=example,DC=net:DN的表示 | 
| IA5 String | 零个或多个International Alphabet 5的字符 | 
| Integer | 整形 | 
| Octet String | 八进制字符串 | 
| OID | Object Identifier,对象唯一标识符,比如: 1.3.6.1.4.1.1466.115.121.1.38 | 
常见匹配规则如下:
| 规则 | 说明 | 
|---|---|
| bitStringMatch | 每一个bit都要相等 | 
| booleanMatch | 布尔匹配 | 
| caseIgnoreMatch | 忽略大小写匹配 | 
| caseIgnoreListMatch | 列表匹配,列表中的内容忽略大小写 | 
| caseIgnoreIA5Match | 忽略大小写的International Alphabet 5字符匹配 | 
| integerMatch | 整型匹配 | 
接下来介绍如何在Windows系统快速搭建LDAP服务器,在使用了ApacheDs、OpenLdap、OpenDJ后,最终选择了OpenDJ。
 OpenDJ是符合LDAPv3的目录服务,它是为Java(JRE 8、11、17、19)平台开发的,为组织及身份的管理提供了高性能、高可用性、高安全性的存储。其安装过程简单,加上Java平台的强大功能,使OpenDJ成为最易于部署和管理的LDAP服务端。
注:
关于OpenDJ部署的更多说明可参见:
https://github.com/OpenIdentityPlatform/OpenDJ/wiki/Installation-Guide
下载链接:https://github.com/OpenIdentityPlatform/OpenDJ/releases/tag/4.5.4
 
下载opendj-4.5.4.zip后,解压缩后运行setup.bat(切记以管理员身份运行):
 
 之后一直点击下一步即可,关键设置可参见如下截图:
 


 
在安装完成后,可通过点击解压目录下的bat/control-panel.bat启动OpenDJ控制面板,如下图根据之前设置的超级用户DN及密码连接本地LDAP服务:
 
 连接成功后即可进入OpenDJ控制面板主页:
 
 点击面板主页左侧菜单目录数据->管理条目即可进入如下条目管理页面,
 如下图中可以看见我们之前安装时设置的Base DN: dc=mydomain,dc=com:
 
在OpenDJ控制面板主页可以通过点击导入LDIF快速导入数据:
LDIF - LDAP Data Interchange Format,数据交换格式,是LDAP数据库信息的一种文本格式,用于数据的导入导出,每行都是 属性: 值

导入ldap_data.ldif内容如下:
# 创建DC - Domain Component
dn: dc=mydomain,dc=com
objectclass: domain
dc: mydomain# 创建组织机构people - Organizational Units
dn: ou=people,dc=mydomain,dc=com
objectclass: organizationalUnit
ou: people# 创建组部门technology - Organizational Units
dn: ou=technology,ou=people,dc=mydomain,dc=com
objectclass: organizationalUnit
ou: technology# 创建组部门marketing - Organizational Units
dn: ou=marketing,ou=people,dc=mydomain,dc=com
objectclass: organizationalUnit
ou: marketing# 创建用户 - inetOrgPerson
dn: cn=luohq,ou=technology,ou=people,dc=mydomain,dc=com
objectclass: inetOrgPerson
cn: luohq
sn: luo
mail: luohq@mydomain.com
userPassword: 123456dn: cn=liuy,ou=technology,ou=people,dc=mydomain,dc=com
objectclass: inetOrgPerson
cn: liuy
sn: liu
mail: liuy@mydomain.com
userPassword: 123456
 
导入成功后通过管理条目查看LDAP数据如下图:
 
虽然在之前搭建LDAP服务时使用了OpenDj自带的控制面板,但是在实际使用过程中总是出现控制面板程序无故挂掉的情况。故在实际使用过程中,推荐使用Apache Directory Studio管理工具,相较于OpenDJ自带的控制面板更稳定、功能也比较全面(支持Entry管理、Schema查看、导入、导出等),感兴趣的小伙伴可自行探索。
 
之后会单独写篇文章介绍Spring集成LDAP,包括:
参考:
Authing - 可能是最详细的LDAP讲解
 LDAP介绍 - ObjectClass类型及继承
开源实现推荐:
 https://opensource.com/business/14/5/four-open-source-alternatives-LDAP
ApacheDS:
 不要用 Apache Directory Server
 https://directory.apache.org/
 如何使用Apache Directory Studio
OpenLDAP:
 https://directory.apache.org/
 Windows下安装使用OpenLDAP:
 https://www.maxcrc.de/en/openldap-for-windows-installation-en/
 https://www.cnblogs.com/lcword/p/14434445.html
 https://blog.csdn.net/oscar999/article/details/108654461
OpenDJ:
 https://www.openidentityplatform.org/opendj
 安装OpenDJ Windows -https://support.ptc.com/help/acd_admin/r7.2.0.0/en/index.html#page/acd_admin/deployment_guide_files/Installing_OpenDJ.html
LDAP Browser:
 https://ldapbrowserwindows.com/
Spring Ldap:
 https://www.baeldung.com/spring-ldap
 https://www.baeldung.com/spring-data-ldap
 https://www.baeldung.com/java-ldap-auth
 Spring LdapTemplate:
 https://blog.jayway.com/2009/02/02/simple-authentication-using-spring-ldap/
 https://memorynotfound.com/spring-boot-spring-ldap-advanced-ldap-queries-example/
 https://java.hotexamples.com/examples/org.springframework.ldap.core/LdapTemplate/search/java-ldaptemplate-search-method-examples.html