Blog Post

LDAP 的介绍与应用

一、LDAP 介绍

什么是 LDAP ?

LDAP 全称为 Light Directory Access Protocol 轻量级目录访问协议, LDAP目录以树状的结构来存储数据,可以理解为一个目录数据库。

目录数据库(LDAP)与关系类型数据库(MySQL)的区别?

LDAP 读性能好,但写性能差,不支持事务处理、回滚等复杂功能,不适用与频繁的数据更新场景,主要还是应用于读多写少场景。关系数据库表则是将数据是以行列的形式存储在一张表中,而LDAP 数据库则是将数据组织成一个树形结构,数据存储在叶子节点。

关系类型表的数据结构

组织机构表结构 (dept)

iddept_name1技术部2市场部

用户表结构 (user)

idaccountnamepasswordphonedept_name1zhangsan张三12345613112345678技术部2lisi李四65432113156781234市场部

LDAP 目录数据结构

LDAP 能干点啥?

账号的统一管理 企业内部有多个第三方系统,每入职一个新员工,管理员需要在每个系统中创建一个账号再发给新员工。而管理员希望能够统一在用户管理系统中统一创建用户,然后可以登录到各个第三方系统中。

用户管理系统为企业内部的用户系统,管理员负责在该系统进行创建用户、更新用户和删除用户等管理操作。用户管理系统需要将用户信息增量的同步到LDAP存储中,而这个过程需要通过开发完成。PHPLDAPAdmin 是LDAP的可视化管理Web端工具。管理员也可以通过PHPLDAPAdmin对LDAP的用户信息进行管理操作,这个工具类似数据库连接工具Navicat,生产环境不建议这样操作。一般是数据出现差异或错误时使用。第三方系统通过支持LDAP协议完成与OpenLDAP服务的登录认证,当用户登录成功后,通过LDAP提供的API获取已登录的用户信息。

整体流程如下:

首先,由管理员再用户管理系统为用户创建登录的用户名和密码等用户信息,或者管理员直接在PHPLDAPAdmin这个Web工具进行创建用户信息。用户管理系统需要将创建的用户信息通过调用LDAP的API实时的写入到LDAP存储中。用户通过管理员创建的账号和密码登录到第三方系统,例如:GitLab。此时 GitLab 与 LDAP 服务进行登录认证。登录认证成功后,GitLab 会获取当前登录的用户数据进行业务处理,创建用户会话。最后, 用户在用户管理系统上更新个人信息或重置密码,用户管理系统需要同步该用户更新的数据。保证用户下次再访问第三方系统时,能够正常登录和获取最新的用户信息。

LDAP 的基本概念

条目(Entry)

目录管理的对象,也称之为一个节点,是LDAP中最基本单元,类似数据库表中的一条记录。通常对LDAP的增删改查都是以条目作为基本对象。

DC,(Domain Component)域的组织,类似关系型中的库名。例如:域名cubigdata.cn 可以表示为 dc=cubigdata,dc=cn。DN,(Distinguished Name)每一个条目都有一个唯一的标识名。例如:“cn=技术部,ou=dept,dc=cubigdata,dc=cn” , 类似行记录中的主键。Base DN,最顶部就是根,如“dc=cubigdata,dc=cn"。OU(Organization Unit),ou 指代组织单元、部门。类似上面图中的技术部、市场部等。

属性(Attribute)

如果条目类似于数据库表中的一条记录,那么属性类似于数据库表中的定义的字段,一个条目(Entry)包含多个属性(Attribute),如果定义用户(User)是一个条目,属性可以由姓名、邮箱、电话等。

对象类(Object Classes)

对象类(Object Classes)与Java中的 Class 是一样的概念,一个对象类中包含多个属性,LDAP 内置一些常见的对象类方便自定义时进行继承,对象类主要用于定义 Schema。

模式(Schema)

模式(Schema)*类似数据库中的Schema 用于定义了表结构、属性字段和语法格式。而 LDAP 的 Schema 中包含了 对象类(ObjectClass)、属性(AttributeType)、语法(Syntax),用于条目数据在导入时进行模式检查,确保目录中所有的条目数据结构是一致的。

二、LDAP 安装部署

镜像下载

openldap LDAP服务目录 docker pull osixia/openldap:latestphpldapadmin docker pull osixia/phpldapadmin:latest

启动镜像

启动 openldap 服务

docker run -d \

--name openldap \

--hostname openldap \

-p 389:389 \

-p 636:636 \

-e LDAP_ORGANISATION="cubigdata" \

-e LDAP_DOMAIN="cubigdata.cn" \

-e LDAP_ADMIN_PASSWORD="123456" \

-v /Users/docker/openldap/ldap:/var/lib/ldap \

-v /Users/docker/openldap/slapd.d:/etc/ldap/slapd.d \

osixia/openldap:latest

命令参数含义-v /Users/docker/openldap/ldap:/var/lib/ldap数据持久化到本地-v /Users/docker/openldap/slapd.d:/etc/ldap/slapd.d配置持久化到本地-p 389:389TCP/IP 访问端口-p 636:636SSL 连接端口–env LDAP_ORGANISATION=“cubigdata”配置 LDAP 域名–env LDAP_DOMAIN=“cubigdata.cn”配置 LDAP 组织名称–env LDAP_ADMIN_PASSWORD=“123456”配置 LDAP 密码

启动 phpldapadmin

docker run -d -p 8060:80 \

--name phpldapadmin \

-e PHPLDAPADMIN_HTTPS=false \

-e PHPLDAPADMIN_LDAP_HOSTS=172.17.0.4 \

osixia/phpldapadmin:latest

命令参数含义-e PHPLDAPADMIN_HTTPS关闭HTTPS访问-e PHPLDAPADMIN_LDAP_HOSTS指定OpenLDAP服务的地址,这里配置的是容器内IP

登录访问

输入访问地址:http://localhost:8060/Login(DN):cn=admin,dc=cubigdata,dc=cnPassword:123456

创建用户数据

首先,创建两个组织单元(OU),分别命名为 depts 和 users。 其次,在 depts 下创建一个技术部节点,在users 下创建张三和李四两个账号,密码设置为 123456

创建组织机构 创建用户数据 最后,用户创建完成,下面需要配置一个第三方系统看一下是否可以使用。

三、第三方系统配置 LDAP

ShenYu 网关集成 LDAP

认证流程 用户登录时 Shenyu Admin 服务与 OpenLDAP 服务进行该用户名和密码认证,认证通过后,如果该用户不存在,Shenyu Admin 将保存该用户信息到用户表中。添加配置

shenyu:

ldap:

enabled: true

url: ldap://127.0.0.1:389

bind-dn: cn=admin,dc=cubigdata,dc=cn

password: 123456

base-dn: ou=users,dc=cubigdata,dc=cn

object-class: posixAccount

login-field: uid

配置详解

名称类型默认值是否必填说明enabledbooleantrue否是否启用urlString无是ldap连接地址bind-dnString无否UserDnpasswordString无否密码base-dnString无否searchBaseobject-classStringperson否posixAccountlogin-fieldStringcn否searchBaseconnectTimeoutint3000否连接超时时间(毫秒)readTimeoutint3000否读取操作超时时间(毫秒)

注意:object-class 创建时选择的是 User Account,这里选择对应的是 posixAccount

自定义 Schema

当 LDAP 内置的 ObjectClass 不满足业务需求时,通过自定义方式创建自己的Schema,可以通过如下方式进行。

创建 schema 文件

创建一个sysuser.schema文件,保存如下信息

# 镜像中 vim 命令不存在需要先安装

apt-get update && apt-get install vim

mkdir -p /etc/ldap/schema/selfdefine

vim /etc/ldap/schema/selfdefine/sysuser.schema

# name,email 属性已经为内置属性,所以这里定义为userName和userEmail

attributetype ( 23.8.14.1.1

NAME 'userAccount'

DESC '登录账号'

EQUALITY caseIgnoreMatch

SUBSTR caseIgnoreSubstringsMatch

SYNTAX 1.3.6.1.4.1.1466.115.121.1.15

SINGLE-VALUE)

attributetype ( 23.8.14.1.2

NAME 'userPhone'

DESC '手机号'

EQUALITY caseIgnoreMatch

SUBSTR caseIgnoreSubstringsMatch

SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )

attributetype ( 23.8.14.1.3

NAME 'userEmail'

DESC '邮箱'

EQUALITY caseIgnoreMatch

SUBSTR caseIgnoreSubstringsMatch

SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )

attributetype ( 23.8.14.1.4

NAME 'userName'

DESC '用户姓名'

EQUALITY caseIgnoreMatch

SUBSTR caseIgnoreSubstringsMatch

SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )

objectclass ( 23.8.14.1.100

NAME 'SysUser'

DESC '用户实体'

SUP top

STRUCTURAL

MUST ( userId $ userAccount )

MAY ( userPhone $ userEmail $ userName $ userPassword ))

Must 代表必填字段名MAY 新增的字段名,其中 userPassword 是内置的 (AttributeType)属性

字段含义23.8.14.1.1自定义即可,但需要保证全局唯一NAME字段名称EQUALITY默认caseIgnoreMatch即可。这是LDAP中为了加快查询的速度,针对不同的数据类型,可以提供不同的匹配方法。如针对字符串类型的相等、模糊、大于、小于、子串包含等,这样就为服务器在搜索操作过程中如何比较字符串提供了准则。在查询过程中,匹配规则告知服务器所用的对照顺序及运算符SYNTAX默认1.3.6.1.4.1.1466.115.121.1.15 即可。语法没有名称,所以在使用时应引用OID。语法主要指的是数据类型,LDAP中大部分数据类型是字符型,为了检索的需要,添加了BIN(二进制数据)、CIS(忽略大小写)、CES(大小写敏感)、TEL(电话型)等语(syntax),这些和关系数据库提供的整数、浮点数、日期、货币等类型既有一些相似的地方也略有不同SINGLE-VALUE值唯一

生成LDIF文件

创建配置文件,在文件中加入如下信息

vim /etc/ldap/schema/selfdefine/sysuser.conf

include /etc/ldap/schema/core.schema

include /etc/ldap/schema/selfdefine/sysuser.schema

执行命令生产.ldif 文件

slaptest -f /etc/ldap/schema/selfdefine/sysuser.conf -F /etc/ldap/schema/selfdefine

生成文件目录如下:

修改ldif文件

cd /etc/ldap/schema/selfdefine/cn=config/cn=schema

cp cn={1}sysuser.ldif sysuser.ldif

vi sysuser.ldif

dn 修改为 cn=sysuser,cn=schema,cn=configcn 修改为 cn=sysuser 如下图:

将该文件添加进OpenLDAP库

slapadd -l /etc/ldap/schema/selfdefine/cn=config/cn=schema/sysuser.ldif -n 0

# 查看一下是否添加成功

ls -l /etc/ldap/slapd.d/cn=config/cn=schema/

重启 slapd 服务,这里重启docker即可

docker restart openldap

验证 schema 是否创建成功 点击 schema 列表,搜索 SysUser 如果存在代表添加成功。