文档章节

使用包ldap3进行Python的LDAP操作

shawnplaying
 shawnplaying
发布于 2016/08/16 13:22
字数 1874
阅读 2375
收藏 1
点赞 0
评论 1

背景:我的管理平台系统需要在权限验证方面与ldap集成,所以需要使用python操作LDAP。

本来想使用python-ldap,但是安装过程中出现如下问题,而且花费很多时间精力没有解决该问题,所以放弃python-ldap,而使用ldap3。

E:\>pip install python-ldap
Collecting python-ldap
D:\app\Python27\lib\site-packages\pip\_vendor\requests\packages\urllib3\util\ssl_.py:318: SNIMissingWarning: An HTTPS re
quest has been made, but the SNI (Subject Name Indication) extension to TLS is not available on this platform. This may
cause the server to present an incorrect TLS certificate, which can cause validation failures. You can upgrade to a newe
r version of Python to solve this. For more information, see https://urllib3.readthedocs.org/en/latest/security.html#sni
missingwarning.
  SNIMissingWarning

省略。。。
    C:\Users\zhaoxp2\AppData\Local\Programs\Common\Microsoft\Visual C++ for Python\9.0\VC\Bin\amd64\cl.exe /c /nologo /O
x /MD /W3 /GS- /DNDEBUG -DHAVE_SASL -DHAVE_TLS -DHAVE_LIBLDAP_R -DHAVE_LIBLDAP_R -DLDAPMODULE_VERSION=2.4.27 -IModules -
I/usr/include -I/usr/include/sasl -I/usr/local/include -I/usr/local/include/sasl -ID:\app\Python27\include -ID:\app\Pyth
on27\PC /TcModules/LDAPObject.c /Fobuild\temp.win-amd64-2.7\Release\Modules/LDAPObject.obj
    LDAPObject.c
    c:\users\zhaoxp2\appdata\local\temp\pip-build-kecixv\python-ldap\modules\errors.h(8) : fatal error C1083: Cannot ope
n include file: 'lber.h': No such file or directory
    error: command 'C:\\Users\\zhaoxp2\\AppData\\Local\\Programs\\Common\\Microsoft\\Visual C++ for Python\\9.0\\VC\\Bin
\\amd64\\cl.exe' failed with exit status 2

    ----------------------------------------
Command "D:\app\Python27\python.exe -u -c "import setuptools, tokenize;__file__='c:\\users\\zhaoxp2\\appdata\\local\\tem
p\\pip-build-kecixv\\python-ldap\\setup.py';exec(compile(getattr(tokenize, 'open', open)(__file__).read().replace('\r\n'
, '\n'), __file__, 'exec'))" install --record c:\users\zhaoxp2\appdata\local\temp\pip-f4qvel-record\install-record.txt -
-single-version-externally-managed --compile" failed with error code 1 in c:\users\zhaoxp2\appdata\local\temp\pip-build-
kecixv\python-ldap\

安装ldap3

安装ldap3很简单,pip install ldap3即可。地址:https://pypi.python.org/pypi/ldap3

为什么使用ldap3?下面是给出的原因:

A strictly RFC 4510 conforming LDAP V3 pure Python client library. The same codebase works with Python 2, Python 3, PyPy, PyPy3 and Nuikta.

使用ldap3访问LDAP服务器

接下来是ldap3的使用介绍。

参考:http://ldap3.readthedocs.io/tutorial.html

3种连接方法:

1 anonymous

2 simple password

3 SASL(simple authentication and security layer)

这里注意文档中说明了longin就是bind(后面代码中会有相关参数)。

在API的Connection中定义了5中策略:

  策略 同步否? Return
1 SYNC synchronous True/False
2 ASYNC asynchronous Integer
3 LDIF    
4 RESTARTABLE synchronous True/False
5 REUSABLE asynchronous Integer

在异步模式下,将返回message_id而不是True或者False。另外异步模式下将会调用Connection的get_response(message_id)方法。还可以设置timeout参数。

LDIF模式用来创建LDIF-CHANGEs流。The LDIF strategy is used to create a stream of LDIF-CHANGEs.

默认模式是SYNC。

连接:

>>> server = Server('ipa.demo1.freeipa.org')
>>> conn = Connection(server)
>>> conn.bind()
True

或者

>> conn = Connection('ipa.demo1.freeipa.org', auto_bind=True)
True

查看连接信息:

print server
print conn

获取服务器信息:

>>> server = Server('ipa.demo1.freeipa.org', get_info=ALL)
>>> conn = Connection(server, auto_bind=True)
>>> server.info
DSA info (from DSE):
  Supported LDAP Versions: 2, 3
  Naming Contexts:
    cn=changelog
省略

>>> server.schema
DSA Schema from: cn=schema
  Attribute types:{'ipaNTTrustForestTrustInfo': Attribute type: 2.16.840.1.113730.3.8.11.17
  Short name: ipaNTTrustForestTrustInfo
  Description: Forest trust information for a trusted domain object
省略

登录:

>>> # import class and constants
>>> from ldap3 import Server, Connection, ALL, NTLM

>>> # define the server and the connection
>>> server = Server('10.99.201.86', get_info=ALL)
>>> conn = Connection(server, user="Domain\\User", password="password", authentication=“NTLM”)

查看登录信息:

>>> conn.extend.standard.who_am_i()

如果是匿名登录那么返回空。

所以使用用户名密码登录:

>>> conn = Connection(server, 'uid=admin, cn=users, cn=accounts, dc=demo1, dc=freeipa, dc=org', 'Secret123', auto_bind=True)
>>> conn.extend.standard.who_am_i()
'dn: uid=admin,cn=users,cn=accounts,dc=demo1,dc=freeipa,dc=org'

使用安全方式登录,两种:LDAP over TLS or the StartTLS extended operation。这里不做详细说明,具体参考官方文档。下面只列出相关代码:

>>> server = Server('ipa.demo1.freeipa.org', use_ssl=True, get_info=ALL)
>>> conn = Connection(server, 'uid=admin, cn=users, cn=accounts, dc=demo1, dc=freeipa, dc=org', 'Secret123', auto_bind=True)
>>> print(conn)
ldaps://ipa.demo1.freeipa.org:636 - ssl - user: uid=admin, cn=users, cn=accounts, dc=demo1, dc=freeipa, dc=org - bound - open - <local: 192.168.1.101:51438 - remote: 209.132.178.99:636> - tls not started - listening - SyncStrategy - internal decoder
>>> from ldap3 import Server, Connection, Tls
>>> import ssl
>>> tls_configuration = Tls(validate=ssl.CERT_REQUIRED, version=ssl.PROTOCOL_TLSv1)
>>> server = Server('ipa.demo1.freeipa.org', use_ssl=True, tls=tls_configuration)
>>> conn = Connection(server)
>>> conn.open()
...
ldap3.core.exceptions.LDAPSocketOpenError: (LDAPSocketOpenError('socket ssl wrapping error: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:600)',),)

访问数据

这里介绍同步和异步两种方式。读文档说明,异步是使用独立线程完成操作的。同步的就是发送消息然后等待接受消息。

异步经常用于event-driven,事件驱动。

另外还有一种Compare操作。它既是用来验证一个attribute是否有一个value。这个操作可以用来做密码验证(不用bind操作)。

任何同步操作后Connection对象中都会有一些attribute被populated。

  • result: the result of the last operation (as returned by the server)
  • response: the entries found (if the last operation is a Search)
  • entries: the entries found exposed via the abstraction layer (if the last operation is a Search)
  • last_error: the error occurred in the last operation, if any
  • bound: True if the connection is bound to the server
  • listening: True if the socket is listening to the server
  • closed: True if the socket is not open

搜索操作

搜索操作需要三个参数,但是只有两个是必须:

  • search_base: the location in the DIT where the search will start
  • search_filter: what are you searching

 这里的search_filter有特殊的语法。它是基于assertion,而assertion是一个bracketed expression。assertion是true false或者undefined(等同于false)。assertion使用& | ! 组织,可以包含 = <= >= =* ~=等。另外注意,这里没有 < 和 > 符号。

例如:

(&
    (|
        (givenName=Fred)
        (givenName=John)
    )
    (mail=*@example.org)
)

代码示例:

搜索所有person,即objectclass=persono。

>>> from ldap3 import Server, Connection, ALL
>>> server = Server('ipa.demo1.freeipa.org', get_info=ALL)
>>> conn = Connection(server, 'uid=admin, cn=users, cn=accounts, dc=demo1, dc=freeipa, dc=org', 'Secret123', auto_bind=True)
>>> conn.search('dc=demo1, dc=freeipa, dc=org', '(objectclass=person)')
True
>>> conn.entries
[DN: uid=admin,cn=users,cn=accounts,dc=demo1,dc=freeipa,dc=org
, DN: uid=manager,cn=users,cn=accounts,dc=demo1,dc=freeipa,dc=org
, DN: uid=employee,cn=users,cn=accounts,dc=demo1,dc=freeipa,dc=org
, DN: uid=helpdesk,cn=users,cn=accounts,dc=demo1,dc=freeipa,dc=org
]

请求获取部分属性。

>>> conn.search('dc=demo1, dc=freeipa, dc=org', '(&(objectclass=person)(uid=admin))', attributes=['sn','krbLastPwdChange', 'objectclass'])
True
>>> conn.entries[0]
DN: uid=admin,cn=users,cn=accounts,dc=demo1,dc=freeipa,dc=org
    krbLastPwdChange: 2015-09-30 04:06:59+00:00
    objectclass: top
                 person
                 posixaccount
                 krbprincipalaux
                 krbticketpolicyaux
                 inetuser
                 ipaobject
                 ipasshuser
                 ipaSshGroupOfPubKeys
    sn: Administrator

属性获取方法:

>>> entry = entries[0]
>>> entry.krbLastPwdChange
krbLastPwdChange: 2015-09-30 04:06:59+00:00
>>> entry.KRBLastPwdCHANGE
krbLastPwdChange: 2015-09-30 04:06:59+00:00
>>> entry['krbLastPwdChange']
krbLastPwdChange: 2015-09-30 04:06:59+00:00
>>> entry['KRB LAST PWD CHANGE']
krbLastPwdChange: 2015-09-30 04:06:59+00:00

>>> entry.krbLastPwdChange.values
[datetime.datetime(2015, 9, 30, 4, 6, 59, tzinfo=OffsetTzInfo(offset=0, name='UTC'))]
>>> entry.krbLastPwdChange.raw_values
[b'20150930040659Z']

一点要注意,那就是search_scope表示了搜索范围,有三种。默认SUBTREE。

1 BASE A base search limits the search to the base object 一般用来检查object的存在与否。
2 LEVEL A one-level search is restricted to the immediate children of a base object, but excludes the base object itself. 
3 SUBTREE A subtree search (or a deep search) includes all child objects as well as the base object. 

 

关于LDIF:

>>> print(conn.entries[0].entry_to_ldif())
version: 1
dn: uid=admin,cn=users,cn=accounts,dc=demo1,dc=freeipa,dc=org
objectclass: top
objectclass: person
objectclass: posixaccount
objectclass: krbprincipalaux
objectclass: krbticketpolicyaux
objectclass: inetuser
objectclass: ipaobject
objectclass: ipasshuser
objectclass: ipaSshGroupOfPubKeys
krbLastPwdChange: 20150930040659Z
sn: Administrator
# total number of entries: 1

或者使用JSON表示:

>>> print(entry.entry_to_json())
{
    "attributes": {
        "krbLastPwdChange": [
            "2015-09-30 04:06:59+00:00"
        ],
        "objectclass": [
            "top",
            "person",
            "posixaccount",
            "krbprincipalaux",
            "krbticketpolicyaux",
            "inetuser",
            "ipaobject",
            "ipasshuser",
            "ipaSshGroupOfPubKeys"
        ],
        "sn": [
            "Administrator"
        ]
    },
    "dn": "uid=admin,cn=users,cn=accounts,dc=demo1,dc=freeipa,dc=org"

另外关于binary values:

>>> from ldap3.utils.conv import escape_bytes
>>> unique_id = b'\xca@\xf2k\x1d\x86\xcaL\xb7\xa2\xca@\xf2k\x1d\x86'
>>> search_filter = '(nsUniqueID=' + escape_bytes(unique_id) + ')'
>>> conn.search('dc=demo1, dc=freeipa, dc=org', search_filter, attributes=['nsUniqueId'])

关于connection context manager:

>>> with Connection(server, 'uid=admin, cn=users, cn=accounts, dc=demo1, dc=freeipa, dc=org', 'Secret123') as conn:
        conn.search('dc=demo1, dc=freeipa, dc=org', '(&(objectclass=person)(uid=admin))', attributes=['sn','krbLastPwdChange', 'objectclass'])
        entry = conn.entries[0]
True
>>> conn.bound
False
>>> entry
DN: uid=admin,cn=users,cn=accounts,dc=demo1,dc=freeipa,dc=org
krbLastPwdChange: 2015-09-30 04:06:59+00:00
objectclass: top
             person
             posixaccount
             krbprincipalaux
             krbticketpolicyaux
             inetuser
             ipaobject
             ipasshuser
             ipaSshGroupOfPubKeys
sn: Administrator

增加操作

>>> # Create a container for our new entries
>>> conn.add('ou=ldap3-tutorial, dc=demo1, dc=freeipa, dc=org', 'organizationalUnit')
>>> True
>>> # Add some users
>>> conn.add('cn=b.young,ou=ldap3-tutorial,dc=demo1,dc=freeipa,dc=org', 'inetorgperson', {'givenName': 'Beatrix', 'sn': 'Young', 'departmentNumber':'DEV', 'telephoneNumber': 1111})
>>> True
>>> conn.add('cn=j.smith,ou=ldap3-tutorial,dc=demo1,dc=freeipa,dc=org', 'inetorgperson', {'givenName': 'John', 'sn': 'Smith', 'departmentNumber':'DEV',  'telephoneNumber': 2222})
>>> True
>>> conn.add('cn=m.smith,ou=ldap3-tutorial,dc=demo1,dc=freeipa,dc=org', 'inetorgperson', {'givenName': 'Marianne', 'sn': 'Smith', 'departmentNumber':'QA',  'telephoneNumber': 3333})
>>> True
>>> conn.add('cn=quentin.cat,ou=ldap3-tutorial,dc=demo1,dc=freeipa,dc=org', 'inetorgperson', {'givenName': 'Quentin', 'sn': 'Cat', 'departmentNumber':'CC',  'telephoneNumber': 4444})

 

© 著作权归作者所有

共有 人打赏支持
shawnplaying
粉丝 14
博文 126
码字总数 70642
作品 0
海淀
系统管理员
加载中

评论(1)

abelhu
abelhu
博主,我想问下,你在连接的时候用普通用户可以登录吗,我按照你的做的,管理员可以登录,但是普通用户就不可以,你之前与大奥过吗
pycharm中使用anaconda

source activate python34 # for Linux & Mac# 激活后,会发现terminal输入的地方多了python34的字样,实际上,此时系统做的事情就是把默认2.7环境从PATH中去除,再把3.4对应的命令加入PATH#...

h8b6pk7m7r8 ⋅ 01/07 ⋅ 0

PyQT5速成教程-1 简介与环境搭建

PyQt简介 一个良好的界面是人机交互中十分重要的一环。 Python作为脚本语言,起初并未拥有GUI开发的部分。但随着其开放的扩展性,使得Python不断壮大,有PyQt、Tkinter,PyGUI等GUI Toolkit...

养薛定谔的猫 ⋅ 06/02 ⋅ 0

mysql闪回工具binlog2sql 安装使用

软件包下载地址:链接:https://pan.baidu.com/s/15dDeGufVWOgVrfATGWBzaA 密码:gnz8 DBA或开发人员,有时会误删或者误更新数据,如果是线上环境会影响较大,这就需要能快速回滚;而MySQL闪回...

DB蜗牛 ⋅ 05/09 ⋅ 0

Python发展迅速,成为学术界新主流

如果说2018年以前R是数据学术界的主流,但是现在Python正在慢慢取代R在学术界的地位。 Python与R相比速度要快。Python可以直接处理上G的数据;R不行,R分析数据时需要先通过数据库把大数据转...

Python燕大侠 ⋅ 05/07 ⋅ 0

Python Scrapy 爬虫(三):部署环境搭建

当我们的爬虫程序开发完成后,应该考虑的事情就是如何将我们的爬虫程序部署到我们的服务器上来运行了。 下面就以 CentOS 作为我们的爬虫程序的部署环境来介绍部署爬虫的第一步:部署环境搭建...

雨林_a1d6 ⋅ 05/29 ⋅ 0

Linux环境下的Anaconda安装及使用

Anaconda对于python就相当于Ubuntu对于Linux,即Anaconda是python的一个发行版,将python和许多常用的package打包,方便pythoners直接使用。像virtualenv、pyenv等工具管理虚拟环境,起到的作...

戴千岩 ⋅ 2017/09/24 ⋅ 0

Python数据科学(八)- 资料探索与资料视觉化

传送门: Python数据科学(一)- python与数据科学应用(Ⅰ) Python数据科学(二)- python与数据科学应用(Ⅱ) Python数据科学(三)- python与数据科学应用(Ⅲ) Python数据科学(四)- 数据收...

_知几 ⋅ 05/22 ⋅ 0

Anaconda 一次更新所有库

使用 Anaconda 管理 Python 的包非常方便,大部分的 Python 包都可以通过 Anaconda 进行安装。 但在使用 Anaconda 升级包的时候,发现在 Anaconda Navigator 界面上点击升级的方法不好使,点...

DreamOver ⋅ 04/16 ⋅ 0

Centos7安装Python3并兼容Python2的方法

Centos7安装Python3的方法 由于centos7原本就安装了Python2,而且这个Python2不能被删除,因为有很多系统命令,比如yum都要用到。 [root@VM_105_217_centos Python-3.6.2]# pythonPython 2....

宿小帅 ⋅ 06/01 ⋅ 0

大数据分析挖掘学习方向?数据分析师的就业前景怎么样?

加米谷数据分析挖掘课程明细,从理论到云端实操环境到项目实战,手把手教您从0掌握数据分析与挖掘技术,带您走进数据时代。 第一阶段(python基础) python入门:1、Python版本特性介绍2、P...

加米谷大数据 ⋅ 04/17 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

JavaScript零基础入门——(十一)JavaScript的DOM操作

JavaScript零基础入门——(十一)JavaScript的DOM操作 大家好,欢迎回到我们的JavaScript零基础入门。最近有些同学问我说,我讲的的比书上的精简不少。其实呢,我主要讲的是我在开发中经常会...

JandenMa ⋅ 28分钟前 ⋅ 0

volatile和synchronized的区别

volatile和synchronized的区别 在讲这个之前需要先了解下JMM(Java memory Model :java内存模型):并发过程中如何处理可见性、原子性、有序性的问题--建立JMM模型 详情请看:https://baike.b...

MarinJ_Shao ⋅ 55分钟前 ⋅ 0

深入分析Kubernetes Critical Pod(一)

Author: xidianwangtao@gmail.com 摘要:大家在部署Kubernetes集群AddOn组件的时候,经常会看到Annotation scheduler.alpha.kubernetes.io/critical-pod"="",以表示这是一个关键服务,那你知...

WaltonWang ⋅ 今天 ⋅ 0

原子性 - synchronized关键词

原子性概念 原子性提供了程序的互斥操作,同一时刻只能有一个线程能对某块代码进行操作。 原子性的实现方式 在jdk中,原子性的实现方式主要分为: synchronized:关键词,它依赖于JVM,保证了同...

dotleo ⋅ 今天 ⋅ 0

【2018.06.22学习笔记】【linux高级知识 14.4-15.3】

14.4 exportfs命令 14.5 NFS客户端问题 15.1 FTP介绍 15.2/15.3 使用vsftpd搭建ftp

lgsxp ⋅ 今天 ⋅ 0

JeeSite 4.0 功能权限管理基础(Shiro)

Shiro是Apache的一个开源框架,是一个权限管理的框架,实现用户认证、用户授权等。 只要有用户参与一般都要有权限管理,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户...

ThinkGem ⋅ 昨天 ⋅ 0

python f-string 字符串格式化

主要内容 从Python 3.6开始,f-string是格式化字符串的一种很好的新方法。与其他格式化方式相比,它们不仅更易读,更简洁,不易出错,而且速度更快! 在本文的最后,您将了解如何以及为什么今...

阿豪boy ⋅ 昨天 ⋅ 0

Python实现自动登录站点

如果我们想要实现自动登录,那么我们就需要能够驱动浏览器(比如谷歌浏览器)来实现操作,ChromeDriver 刚好能够帮助我们这一点(非谷歌浏览器的驱动有所不同)。 一、确认软件版本 首先我们...

blackfoxya ⋅ 昨天 ⋅ 0

线性回归原理和实现基本认识

一:介绍 定义:线性回归在假设特证满足线性关系,根据给定的训练数据训练一个模型,并用此模型进行预测。为了了解这个定义,我们先举个简单的例子;我们假设一个线性方程 Y=2x+1, x变量为商...

wangxuwei ⋅ 昨天 ⋅ 0

容器之查看minikue的environment——minikube的环境信息

执行如下命令 mjduan@mjduandeMacBook-Pro:~/Docker % minikube docker-envexport DOCKER_TLS_VERIFY="1"export DOCKER_HOST="tcp://192.168.99.100:2376"export DOCKER_CERT_PATH="/U......

汉斯-冯-拉特 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部