DAP(Lightweight Directory Access Protocol,轻量目录访问协议)是一种开放、基于 TCP/IP 的应用层协议,用于访问与维护分布式目录信息,核心特点是读多写少、树状层级存储,常用于企业身份认证与集中权限管理。
一、 核心概念
| 术语 | 萌化解释 | 二次元场景举例 |
|---|---|---|
| DIT(目录信息树) | 像一棵「企业身份家族树」,从根到叶子层层分支 | 根节点dc=company,dc=com→ 分支ou=技术部→ 叶子cn=张三 |
| 条目(Entry) | 树上的每一个「小节点」,存着一个实体的信息 | 一个用户、一个部门、一台服务器(都是树的崽崽) |
| DN(唯一标识) | 节点的「完整家庭住址」,全网唯一 | cn=张三,ou=技术部,dc=company,dc=com(张三住在技术部小区 company 街道) |
| RDN(相对标识) | 家庭住址的「房间号」,同楼层唯一 | cn=张三(技术部里只有一个张三) |
| 属性(Attribute) | 节点的「个人名片」,键值对形式 | uid=zhangsan、mail=zhangsan@company.com、userPassword=123456 |
| 对象类(ObjectClass) | 节点的「身份模板」,规定必须带哪些名片 | inetOrgPerson(人类用户模板)、groupOfNames(部门小组模板) |
| BaseDN(查询起点) | 「找人的起始楼层」,缩小搜索范围 | 查技术部的人就从ou=技术部,dc=company,dc=com开始找 |
二、 工作原理
1. 通信模型
- 角色:LDAP 客户端(请求方) ↔ LDAP 服务端(目录树守护者)
- 端口:389(明文通道,不安全)、636(LDAPS 加密通道,带 SSL 护盾)
- 传输协议:TCP(可靠连接,不掉包)
2. 核心流程(4步曲)
| 步骤 | 拟人化动作 | 技术说明 |
|---|---|---|
| ① 连接 | 客户端敲门:「开门!我要查户口!」 | 建立 TCP 连接 |
| ② 绑定(Bind) | 出示身份证/密码:「我是管理员,权限全开!」 | 认证方式:匿名(游客)、简单密码(普通用户)、SASL(高级加密) |
| ③ 操作 | 查人/加人/改信息:「给我找技术部的张三!」 | 执行 Search/Add/Modify/Delete 操作 |
| ④ 解绑(Unbind) | 挥手告别:「查完啦,关门!」 | 断开连接,释放资源 |
3. 常用操作
- Search(搜索):最常用!支持条件过滤,比如
(uid=zhangsan)(找 uid 是 zhangsan 的人) - Add/Delete:给目录树「添新叶子」或「砍废叶子」
- Modify:修改节点的「个人名片」(比如改密码、换邮箱)
三、 典型应用场景
| 场景 | 漫画剧情 | 技术价值 |
|---|---|---|
| 统一身份认证 | 员工用同一个账号登录 Jenkins、Nginx、OA 系统,不用记一堆密码 | 实现 SSO 单点登录,运维少挨骂 |
| 部门权限管理 | 「技术部小组」有代码库权限,「行政部小组」只有考勤系统权限 | 按组授权,权限管理更清晰 |
| 设备资产管理 | 目录树里存着所有打印机、服务器的信息,输入型号就能查到位置 | 资产查询秒级响应,运维效率up |
| 组织架构维护 | 新员工入职→添加条目到「技术部」,离职→删除条目,自动回收权限 | 人员变动一键同步,减少安全漏洞 |
四、 实战手册:OpenLDAP 快速部署(Ubuntu 22.04 版)
前置条件
- 一台 Ubuntu 22.04 服务器(内存 ≥ 1G)
- 域名或 IP(示例:
ldap.company.com) - 管理员权限(sudo 权限)
步骤 1:安装 OpenLDAP 与配套工具
# 1. 更新软件源sudoaptupdate&&sudoaptupgrade -y# 2. 安装 OpenLDAP 服务 + 管理工具sudoaptinstall-y slapd ldap-utils# 3. 配置 slapd(安装时弹出交互框,按提示填)# ① OLC database backend: MDB(默认,高性能)# ② DNS domain name: company.com(你的域名)# ③ Organization name: Company(组织名)# ④ Administrator password: 设置管理员密码(如 123456)# ⑤ Confirm password: 重复密码# ⑥ Do you want to allow LDAPv2 protocol? No(禁用旧协议)步骤 2:配置 slapd 核心参数(修改配置文件)
OpenLDAP 的配置存储在 LDAP 目录中,需用ldapmodify命令修改。
(1)启用成员索引(提升组查询速度)
创建配置文件member_index.ldif:
dn: cn=module{0},cn=config changetype: modify add: olcModuleLoad olcModuleLoad: memberof.la dn: olcOverlay={0}memberof,olcDatabase={1}mdb,cn=config changetype: add objectClass: olcMemberOf objectClass: olcOverlayConfig objectClass: olcConfig objectClass: top olcOverlay: memberof olcMemberOfDangling: ignore olcMemberOfRefInt: TRUE olcMemberOfGroupOC: groupOfNames olcMemberOfMemberAD: member olcMemberOfMemberOfAD: memberOf执行配置:
sudoldapmodify -Y EXTERNAL -H ldapi:/// -f member_index.ldif(2)配置访问控制(ACL)
创建acl.ldif,允许匿名查询、管理员修改:
dn: olcDatabase={1}mdb,cn=config changetype: modify replace: olcAccess olcAccess: to attrs=userPassword,shadowLastChange by dn="cn=admin,dc=company,dc=com" write by anonymous auth by self write by * none olcAccess: to * by dn="cn=admin,dc=company,dc=com" write by self read by * read执行配置:
sudoldapmodify -Y EXTERNAL -H ldapi:/// -f acl.ldif步骤 3:初始化用户与组(批量添加脚本)
(1)创建基础目录结构(base.ldif)
# 根节点 dn: dc=company,dc=com objectClass: top objectClass: dcObject objectClass: organization o: Company dc: company # 部门:技术部 dn: ou=tech,dc=company,dc=com objectClass: top objectClass: organizationalUnit ou: tech # 部门:行政部 dn: ou=admin,dc=company,dc=com objectClass: top objectClass: organizationalUnit ou: admin # 组:技术部员工组 dn: cn=tech-group,ou=tech,dc=company,dc=com objectClass: top objectClass: groupOfNames cn: tech-group member: cn=zhangsan,ou=tech,dc=company,dc=com(2)添加用户(users.ldif)
# 用户:张三(技术部) dn: cn=zhangsan,ou=tech,dc=company,dc=com objectClass: top objectClass: inetOrgPerson cn: zhangsan sn: zhang uid: zhangsan mail: zhangsan@company.com userPassword: {SSHA}加密后的密码 # 生成方式:slappasswd -s 123456 displayName: 张三 title: 后端开发 # 用户:李四(行政部) dn: cn=lisi,ou=admin,dc=company,dc=com objectClass: top objectClass: inetOrgPerson cn: lisi sn: li uid: lisi mail: lisi@company.com userPassword: {SSHA}加密后的密码 displayName: 李四 title: 行政专员(3)批量导入数据
# 生成加密密码(示例:密码 123456)slappasswd -s123456# 复制输出的 {SSHA}xxx 到 users.ldif 中# 导入基础结构sudoldapadd -x -Dcn=admin,dc=company,dc=com -w123456-f base.ldif# 导入用户sudoldapadd -x -Dcn=admin,dc=company,dc=com -w123456-f users.ldif步骤 4:验证部署结果
# 搜索技术部所有用户ldapsearch -x -bou=tech,dc=company,dc=com -s sub"(objectClass=inetOrgPerson)"# 搜索技术部组的成员ldapsearch -x -bcn=tech-group,ou=tech,dc=company,dc=com -s base"(objectClass=groupOfNames)"✅ 成功标志:输出用户和组的详细信息
五、 实战手册:Spring Boot 集成 OpenLDAP
步骤 1:添加依赖(pom.xml)
<dependencies><!-- Spring Boot Web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Spring Security + LDAP 集成 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-ldap</artifactId></dependency><!-- LDAP 客户端工具 --><dependency><groupId>com.unboundid</groupId><artifactId>unboundid-ldapsdk</artifactId><scope>runtime</scope></dependency></dependencies>步骤 2:配置 LDAP 连接(application.yml)
spring:# LDAP 连接配置ldap:urls:ldap://ldap.company.com:389# 你的 LDAP 服务器地址base:dc=company,dc=com# 根目录username:cn=admin,dc=company,dc=com# 管理员 DNpassword:123456# 管理员密码# Spring Security 配置security:ldap:user:dn-pattern:cn={0},ou={1}# 用户 DN 模板:cn=用户名,ou=部门group:search-base:ou=tech# 组搜索起点search-filter:(member={0})# 组过滤规则:成员包含该用户# 日志配置:打印 LDAP 交互细节(排错用)logging:level:org.springframework.security.ldap:DEBUGorg.springframework.ldap:DEBUG步骤 3:编写 Security 配置类
importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.security.config.annotation.web.builders.HttpSecurity;importorg.springframework.security.config.annotation.web.configuration.EnableWebSecurity;importorg.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider;importorg.springframework.security.web.SecurityFilterChain;@Configuration@EnableWebSecuritypublicclassLdapSecurityConfig{// 配置安全过滤链@BeanpublicSecurityFilterChainsecurityFilterChain(HttpSecurityhttp)throwsException{returnhttp.authorizeHttpRequests(auth->auth.anyRequest().authenticated()// 所有请求都需要认证).formLogin()// 启用表单登录.and().logout().and().ldapAuthentication()// 启用 LDAP 认证.userDnPatterns("cn={0},ou=tech","cn={0},ou=admin")// 支持多部门用户.groupSearchBase("ou=tech")// 搜索技术部的组.groupSearchFilter("(member={0})").and().build();}}步骤 4:编写测试接口
importorg.springframework.security.core.Authentication;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RestController;@RestControllerpublicclassTestController{// 获取当前登录用户信息@GetMapping("/user/info")publicAuthenticationgetUserInfo(Authenticationauthentication){returnauthentication;}}步骤 5:启动测试
- 启动 Spring Boot 应用
- 访问
http://localhost:8080/user/info→ 跳转到登录页 - 输入用户名
zhangsan、密码123456→ 成功返回用户认证信息
六、 常见问题排查清单(踩坑指南)
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 连接失败:Connection refused | 1. LDAP 服务未启动 2. 端口 389/636 被防火墙拦截 3. 服务器地址写错 | 1. 启动服务:sudo systemctl start slapd2. 开放端口: sudo ufw allow 3893. 检查 spring.ldap.urls配置 |
| 认证失败:Bad credentials | 1. 密码错误 2. 用户 DN 模板配置错误 3. 密码加密方式不兼容 | 1. 验证密码:ldapwhoami -x -D cn=zhangsan,ou=tech,dc=company,dc=com -w 1234562. 检查 user-dn-patterns是否匹配用户 DN3. 统一使用 SSHA 加密: slappasswd -s 密码 |
| 搜索不到用户:No such object | 1. BaseDN 配置错误 2. 条目未正确导入 3. ACL 权限不足 | 1. 核对spring.ldap.base是否和 LDAP 根一致2. 重新导入 base.ldif和users.ldif3. 检查 ACL 配置,确保允许读取权限 |
| 启动报错:LDAP context initialization failed | 1. 管理员 DN 写错 2. 管理员密码错误 | 1. 验证管理员 DN:ldapsearch -x -D cn=admin,dc=company,dc=com -w 123456 -b dc=company,dc=com2. 核对 spring.ldap.password配置 |
| 组权限不生效 | 1. 组搜索路径错误 2. 组过滤规则错误 | 1. 检查group-search-base是否指向组所在 OU2. 确认 group-search-filter为(member={0}) |
七、 最佳实践(运维小姐姐的小贴士)
- 加密传输:生产环境一定要用 LDAPS(636 端口),避免密码明文传输。
- 最小权限:应用对接 LDAP 时,不要用管理员账号,创建只读权限的专用账号。
- 定期备份:用
slapcat命令备份 LDAP 数据:slapcat -l ldap_backup.ldif。 - 索引优化:对
uid、mail、member等常用字段创建索引,提升查询速度。
- 博客园
- 公众号
行走之飞鱼