4. LDAP 目录结构设计:组织单元、用户条目与组条目 Schema
LDAP 目录是认证授权平台的身份数据核心。本章围绕 组织单元 (OU)、用户条目 (inetOrgPerson) 和 组条目 (groupOfUniqueNames) 三类核心对象,定义其 Schema 结构与层级关系。设计目标:支撑 Redis 缓存层的高效查询,同时保持 LDAP 原生目录的灵活性与可扩展性。
4.1 目录树顶层结构
采用 扁平化 + 按职能分区 的 OU 设计,避免过深嵌套导致查询性能下降。顶层 OU 划分如下:
| OU 名称 | DN 示例 | 用途 |
|---|---|---|
ou=people |
ou=people,dc=example,dc=com |
存放所有用户条目 (inetOrgPerson) |
ou=groups |
ou=groups,dc=example,dc=com |
存放所有组条目 (groupOfUniqueNames) |
ou=apps |
ou=apps,dc=example,dc=com |
存放应用服务账号 (inetOrgPerson) |
ou=roles |
ou=roles,dc=example,dc=com |
存放角色定义 (groupOfUniqueNames) |
设计原则: 每个 OU 对应一类实体,避免混合存放。这样在 Redis 缓存键设计时,可以直接以 OU 为前缀做批量失效,提升缓存管理效率。
4.2 用户条目 Schema:inetOrgPerson
用户条目使用 inetOrgPerson 对象类,它是 LDAP 标准中描述互联网用户的扩展类,继承自 organizationalPerson 和 person。我们选取以下核心属性用于认证授权场景:
| 属性名 | 类型 | 是否必填 | 说明 |
|---|---|---|---|
uid |
Directory String | 是 | 用户登录名,RDN 属性 |
cn |
Directory String | 是 | 用户全名 |
sn |
Directory String | 是 | 用户姓氏 |
userPassword |
Octet String | 是 | 密码哈希值 (SSHA/BCrypt) |
mail |
Directory String | 否 | 用户邮箱 |
telephoneNumber |
Telephone Number | 否 | 用户电话 |
employeeID |
Directory String | 否 | 员工工号,用于关联业务系统 |
departmentNumber |
Directory String | 否 | 部门编号,用于组织过滤 |
description |
Directory String | 否 | 用户备注 |
LDIF 示例: 创建一个用户条目,RDN 使用
uid,确保唯一性。
dn: uid=zhangsan,ou=people,dc=example,dc=com
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: top
uid: zhangsan
cn: 张三
sn: 张
userPassword: {SSHA}xxxxxxxxxxxxxxxxxxxx
mail: zhangsan@example.com
telephoneNumber: 13800138000
employeeID: EMP2024001
departmentNumber: D001
description: 研发部高级工程师
4.3 组条目 Schema:groupOfUniqueNames
组条目使用 groupOfUniqueNames 对象类,它通过 uniqueMember 属性存储组成员 DN,支持多值。相比 groupOfNames,groupOfUniqueNames 强制成员 DN 唯一,避免重复添加。
| 属性名 | 类型 | 是否必填 | 说明 |
|---|---|---|---|
cn |
Directory String | 是 | 组名称,RDN 属性 |
uniqueMember |
DN | 是 | 组成员 DN,可多值 |
description |
Directory String | 否 | 组描述 |
businessCategory |
Directory String | 否 | 组类别 (如: devops, security, admin) |
性能注意: 当组成员超过 500 时,
uniqueMember 的多值查询会变慢。建议对超大组使用嵌套组结构,或通过 Redis 缓存组成员列表。
dn: cn=devops-team,ou=groups,dc=example,dc=com
objectClass: groupOfUniqueNames
objectClass: top
cn: devops-team
uniqueMember: uid=zhangsan,ou=people,dc=example,dc=com
uniqueMember: uid=lisi,ou=people,dc=example,dc=com
uniqueMember: uid=wangwu,ou=people,dc=example,dc=com
description: DevOps 工程团队
businessCategory: devops
4.4 角色组与权限映射
在 ou=roles 下存放角色定义,每个角色也是一个 groupOfUniqueNames 条目,但 uniqueMember 指向的是 ou=groups 下的组 DN,形成 角色 → 组 → 用户 的间接映射。这种设计支持 RBAC 模型,且角色变更时只需修改角色条目,不影响用户条目。
| 角色 DN | 成员组 DN | 权限范围 |
|---|---|---|
cn=admin-role,ou=roles,... |
cn=admin-group,ou=groups,... |
系统管理权限 |
cn=dev-role,ou=roles,... |
cn=devops-team,ou=groups,... |
开发环境读写权限 |
cn=audit-role,ou=roles,... |
cn=audit-group,ou=groups,... |
审计日志只读权限 |
4.5 Schema 设计检查清单
- 唯一性约束:
uid在ou=people下必须全局唯一,建议在 LDAP 服务端配置uid唯一性插件。 - 密码策略:
userPassword存储哈希值,推荐 SSHA 或 BCrypt;禁止明文存储。 - 索引优化: 为
uid、mail、uniqueMember创建索引,加速认证和组查询。 - 对象类继承: 每个条目必须包含
top对象类,并按照inetOrgPerson或groupOfUniqueNames的继承链完整声明。 - DN 长度控制: 避免 DN 过长(超过 255 字符),否则影响 LDAP 查询性能和 Redis 缓存键长度。
- 审计字段: 建议扩展
inetOrgPerson增加createTimestamp和modifyTimestamp操作属性,用于缓存同步校验。
缓存集成提示: 在 Redis 中缓存用户条目时,使用
uid 作为键的一部分(如 ldap:user:{uid}),缓存组条目时使用 cn(如 ldap:group:{cn})。当 LDAP 条目发生修改时,通过监听 modifyTimestamp 变化来失效对应缓存。