0. ldap 安装 以及接入记录
项目里正好用到了 ldap , 这里我做调试的时候顺便做一个记录
轻型目录访问协议(英文:Lightweight Directory Access Protocol,缩写:LDAP,/ˈɛldæp/)是一个开放的,中立的,工业标准的应用协议,通过IP协
议提供访问控制和维护分布式信息的目录信息。
这里不会关注 LDAP 具体的协议内容和使用语法,需要明确的点在于 LDAP 是一种标准协议,无关底层实现。这意味着实现软件只要支持 LDAP 标准 协议,那么就可以实现无缝对接。当使用 LDAP 协议时,理论上不需要关心具体是 OpenLDAP 提供的服务,或是 Windows Server Active Directory 域服务(以下简称 AD DS)提供的服务,还是其他众多 LDAP 服务器提供的服务。
我们常对接的是 OpenLDAP 和 AD DS。所以下面就以这两种典型的 LDAP 实现做环境搭建和测试。
1. 安装 ldap 服务端
1.1 win
windows 下的安装可以参考: https://bbs.huaweicloud.com/blogs/104955
2008/2012 也都是兼容的
1.2 linux
OpenLDAP 从 0 安装于 CentOS 系统比较繁琐,原因在于需要配置的项目比较多。借助 docker osixia/openldap 镜像几乎可以不做配置,即可快速启 动一个测试环境,启动示例:
docker run -p 389:389 -p 636:636 \
--env LDAP_ORGANISATION="Example Inc." --env LDAP_DOMAIN="acompany.com" \ --env LDAP_ADMIN_PASSWORD="12345678" \
--name cmp-openldap --detach osixia/openldap:1.4.0
1.3 安装完后可以获取下以下ldap信息:
-
域: ACOMPANY (这个字段一般用来跟 sAMAccountName 拼接做 域登陆用)
-
base dn : DC=acompany,DC=com
-
admin bind dn : CN=Administrator,CN=Users,DC=acompany,DC=com (windows下的管理员默认在 Users组织下, 所以这里有 CN=Users , linux 下的 默认管理员 dn 为 cn=admin,dc=acompany,dc=com )
-
admin password : 12345678 (openldap 密码是 docker run指定的, windows 需要手动设置)
2. ldap 客户端
我们分别用 命令行/webui/python3 三种方式来实现 ldap的俩个功能
- 登陆认证
1.1 Distinguished Name 认证 (CN=Administrator,CN=Users,DC=acompany,DC=com)
1.2 域 认证 (ACOMPANY\Administrator)
- 搜索用户
2.1 命令行接入
# 登陆认证
## 认证方式1: 这种方式使用了用户的完整DN(Distinguished Name)作为身份标识。在上述命令中,CN=Administrator,CN=Users,DC=acompany,DC=com 表示了用户 Administrator 的完整DN。
ldapwhoami -x -h yourldap.host -D "CN=Administrator,CN=Users,DC=acompany,DC=com" -w "admin" -p 389
## 认证方式2: 这种方式使用了ACOMPANY\\Administrator 作为用户标识。ACOMPANY是域名,Administrator 是 sAMAccountName 用户名。在一些LDAP服务器中,特定的域用户登录需要使用双反斜杠(\)来转义域名中的反斜杠。
ldapwhoami -x -h yourldap.host -D "ACOMPANY\\Administrator" -w "admin" -p 389
# 登陆认证成功则返回: u:ACOMPANY\Administrator
# 搜索用户
## -s sub 为搜索条件, 这里我们用 & 拼接,可以同时搜索俩个条件,同时表达式也可以用 * 做模糊搜索
## sAMAccountName distinguishedName 为查询返回的字段, 如果不填的话 则返回所有字段
ldapsearch -h yourldap.host -D "CN=Administrator,CN=Users,DC=acompany,DC=com" -w "admin" -p 389 -b 'DC=acompany,DC=com' -s sub '(&(CN=User*)(objectClass=organizationalPerson))' sAMAccountName distinguishedName
# 搜索返回如下:
# user1, Users, acompany.com
dn: CN=user1,CN=Users,DC=acompany,DC=com
distinguishedName: CN=user1,CN=Users,DC=acompany,DC=com
sAMAccountName: user1
# user2, acompany.com
dn: CN=user2,DC=acompany,DC=com
distinguishedName: CN=user2,DC=acompany,DC=com
sAMAccountName: user2
# user3, acompany.com
dn: CN=user3,DC=acompany,DC=com
distinguishedName: CN=user3,DC=acompany,DC=com
sAMAccountName: user3sam
2.2 phpldapadmin 接入
这里用到了一个开源的 phpldapadmin , 也是直接拉一个 docker image起来就能用
不过这个客户端只支持 完整dn登陆, 不支持 域登陆
docker run -p 6443:443 \
--env PHPLDAPADMIN_LDAP_HOSTS=yourldap.host \
--detach osixia/phpldapadmin:0.9.0
2.3 代码接入
from ldap3 import Server, Connection, ALL, ALL_ATTRIBUTES, NTLM, Entry
server = Server('yourldap.host', get_info=ALL)
# 认证方式1: Distinguished Name 认证
conn = Connection(server, 'CN=Administrator,CN=Users,DC=acompany,DC=com', 'admin', auto_bind='NO_TLS')
# 认证方式2: 域认证
conn = Connection(server, 'ACOMPANY\\Administrator', 'admin', auto_bind='NO_TLS')
# 搜索: 这个搜索与命令行方式雷同, 就不多解释了
flag = conn.search('DC=acompany,DC=com', search_filter='(&(objectclass=organizationalPerson))',
attributes=[ALL_ATTRIBUTES])
from typing import List
entry_list: List[Entry] = conn.entries
for item in entry_list:
entry_dict = item.entry_attributes_as_dict
print(f"{entry_dict.get('sAMAccountName')[0]} : {item.entry_dn}")