目录

集成LDAP登录

LDAP 概述

  • LDAP 数据结构为树形结构;
  • LDAP 读性能很好,但写性能很差;
  • LDAP 是一种开放 Internet 标准,LDAP 协议是跨平台的 Internet 协议

LDAP 基本概念

Entry

条目,也叫记录项,是 LDAP 中最基本的颗粒。

  • DN = Distinguished Name 唯一标识名,例如 cn=baby,ou=marketing,dc=mydomain,dc=org

  • RDN 相对唯一标识名,如 cn=baby

  • Base DN 目录树的最顶部,即根,如 dc=mydomain,dc=org

  • DC = Domain Componen

  • OU = Organization Unit 组织单元,单位(部门)名称

  • CN = Common Name 通用名

  • UID = User ID

  • O = Organization 组织

  • C = Country 国家名

ObjectClass

定义

对象类是属性的集合,LDAP 内置了很多人员机构中常见的对象。比如人员(person)含有姓(sn)、名(cn)、电话(telephoneNumber)、密码(userPassword)等属性,单位职工(organizationalPerson)是人员(person)的继承类,除了上述属性之外还含有职务(title)、邮政编码(postalCode)、通信地址(postalAddress)等属性。

作用

通过对象类可以方便的定义条目类型。每个条目可以继承多个对象类,就能拥有不同的属性。

分类

对象类分为三种:结构类型(Structural)、抽象类型(Abstract)和辅助类型(Auxiliary):

  • 结构类型规定了对象实体的基本属性,每个条目属于且仅属于一个结构型对象类,
  • 抽象类型可以是结构类型或其他抽象类型父类,它将对象属性中共性的部分组织在一起,称为其他类的模板,条目不能直接集成抽象型对象类。
  • 辅助类型规定了对象实体的扩展属性。

Schema

对象类(ObjectClass)、属性类型(AttributeType)、语法(Syntax)分别约定了条目、属性和值,他们之间的关系如下图所示。所有这些构成了模式(Schema),即对象类的集合。

搭建 LDAP 测试服务器

使用 docker 安装 OpenLDAP 和 LAM(LDAP Account Manager)。

创建测试网络

1
docker network create --subnet=172.18.0.0/24 ldap

搭建 OpenLDAP 服务

1
2
3
4
5
6
7
docker run -p 127.0.0.1:389:389 -p 127.0.0.1:636:636 \
--env LDAP_ORGANISATION="dota2" --env LDAP_DOMAIN="dota2.com" \
--env LDAP_ADMIN_PASSWORD="[email protected]" \
--name ldap \
--network ldap \
--ip 172.18.0.2 \
-d osixia/openldap

搭建 LAM 服务

1
2
3
4
5
docker run -p 127.0.0.1:1810:80 \
  --name lam \
  --ip 172.18.0.3 \
  --network ldap \
  -d ldapaccountmanager/lam

LAM 配置

打开 http://localhost:1810,在右上角点击 “configuration LAM configuration”,进行配置。默认登录密码为 lam。

在 General Settings 中:

  • Server Settings:修改服务器地址为 ldap://172.18.0.2:389,修改 Tree suffix 为 dc=dota2,dc=com
  • Security Settings:修改管理员用户 DN 为 cn=admin,dc=dota2,dc=com

在 Active Types 中:

  • 配置各 account 的 LDAP suffix 中的 dc 为上述 dc,保留 ou 不变;

保存后,回到主页面登录,使用搭建 OpenLDAP 服务时设置的管理员密码 [email protected] 登录;

简单的 LDAP 登录集成

  1. 使用 admin 用户建立 LDAP 服务器的连接;
  2. 根据用户 ID 或 email 在指定搜索域中查找用户 DN;
  3. 校验用户的凭据;

Python

使用 ldap3 库,ldap3 库是纯 Python 实现,没有依赖,另一个库 python-ldap 需要依赖系统安装 OpenLDAP client。

demo 代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# coding=utf-8

from ldap3 import Connection, Server
from ldap3.core.exceptions import LDAPBindError

LDAP_SERVER = 'localhost'
LDAP_PORT = 389
USE_SSL = False
ADMIN_DN = 'cn=admin,dc=dota2,dc=com'
ADMIN_PASSWORD = '[email protected]'
SEARCH_DOMAIN = 'ou=dev,dc=dota2,dc=com'


def login_user(usermail, password):
    server = Server(LDAP_SERVER, LDAP_PORT, USE_SSL)
    # search
    with Connection(server, ADMIN_DN, ADMIN_PASSWORD, auto_bind=True) as conn:
        found = conn.search(
            SEARCH_DOMAIN,
            f'(mail={usermail})',
            attributes=['cn', 'telephoneNumber'],
        )
        if not found:
            return False
        entry = conn.entries[0]
    # verify
    try:
        with Connection(server, entry.entry_dn, password, auto_bind=True) as conn:
            pass
    except LDAPBindError:
        return False

    entry_data = entry.entry_attributes_as_dict
    return {
        'username': entry_data['cn'][0] if entry_data['cn'] else None,
        'phone': entry_data['telephoneNumber'][0] if entry_data['telephoneNumber'] else None,
        'email': usermail,
    }


if __name__ == "__main__":
    assert login_user('[email protected]', 'test') is True
    assert login_user('[email protected]', 'test123') is False

参考链接