Python使用LDAP做用户认证的方法


Posted in Python onJune 20, 2019

LDAP(Light Directory Access Portocol)是轻量目录访问协议,基于X.500标准,支持TCP/IP。

LDAP目录以树状的层次结构来存储数据。每个目录记录都有标识名(Distinguished Name,简称DN),用来读取单个记录,

一般是这样的:

cn=username,ou=people,dc=test,dc=com

几个关键字的含义如下:

  • base dn:LDAP目录树的最顶部,也就是树的根,是上面的dc=test,dc=com部分,一般使用公司的域名,也可以写做o=test.com,前者更灵活一些。
  • dc::Domain Component,域名部分。
  • ou:Organization Unit,组织单位,用于将数据区分开。
  • cn:Common Name,一般使用用户名。
  • uid:用户id,与cn的作用类似。
  • sn:Surname, 姓。
  • rdn:Relative dn,dn中与目录树的结构无关的部分,通常存在cn或者uid这个属性里。

所以上面的dn代表一条记录,代表一位在test.com公司people部门的用户username。

python-ldap

python一般使用python-ldap库操作ldap,文档:https://www.python-ldap.org/en/latest/index.html。

下载:

pip install python-ldap

还要安装一些环境,ubuntu:

apt-get install build-essential python3-dev python2.7-dev \
  libldap2-dev libsasl2-dev slapd ldap-utils python-tox \
  lcov valgrind

CentOS:

yum groupinstall "Development tools"
yum install openldap-devel python-devel

获取LDAP地址后即可与LDAP建立连接:

import ldap
ldapconn = ldap.initialize('ldap://192.168.1.111:389')

绑定用户,可用于用户验证,用户名必须是dn: 

ldapconn.simple_bind_s('cn=username,ou=people,dc=test,dc=com', pwd)

成功认证时会返回一个tuple:

(97, [], 1, [])

验证失败会报异常ldap.INVALID_CREDENTIALS:

{'desc': u'Invalid credentials'}

注意验证时传空值验证也是可以通过的,注意要对dn和pwd进行检查。

查询LDAP用户信息时,需要登录管理员RootDN帐号:

ldapconn.simple_bind_s('cn=admin,dc=test,dc=com', 'adminpwd')
searchScope = ldap.SCOPE_SUBTREE
searchFilter = 'cn=username'
base_dn = 'ou=people,dc=test,dc=com'
print ldapconn.search_s(base_dn, searchScope, searchFilter, None)

添加用户add_s(dn, modlist),dn为要添加的条目dn,modlist为存储信息:

dn = 'cn=test,ou=people,dc=test,dc=com'
modlist = [
  ('objectclass', ['person', 'organizationalperson'],
  ('cn', ['test']),
  ('uid', [''testuid]),
  ('userpassword', ['pwd']),
]
result = ldapconn.add_s(dn, modlist)

添加成功会返回元组:

(105, [], 2, [])

失败会报ldap.LDAPError异常

Django使用LDAP验证

一个很简单的LDAP验证Backend:

import ldap
class LDAPBackend(object):
  """
  Authenticates with ldap.
  """
  _connection = None
  _connection_bound = False
 
  def authenticate(self, username=None, passwd=None, **kwargs):
    if not username or not passwd:
      return None
    if self._authenticate_user_dn(username, passwd):
      user = self._get_or_create_user(username, passwd)
      return user
    else:
      return None
 
  @property
  def connection(self):
    if not self._connection_bound:
      self._bind()
    return self._get_connection()
 
  def _bind(self):
    self._bind_as(
      LDAP_CONFIG['USERNAME'], LDAP_CONFIG['PASSWORD'], True
    )
 
  def _bind_as(self, bind_dn, bind_password, sticky=False):
    self._get_connection().simple_bind_s(
      bind_dn, bind_password
    )
    self._connection_bound = sticky
 
  def _get_connection(self):
    if not self._connection:
      self._connection = ldap.initialize(LDAP_CONFIG['HOST'])
    return self._connection
 
  def _authenticate_user_dn(self, username, passwd):
    bind_dn = 'cn=%s,%s' % (username, LDAP_CONFIG['BASE_DN'])
    try:
      self._bind_as(bind_dn, passwd, False)
      return True
    except ldap.INVALID_CREDENTIALS:
      return False
 
  def _get_or_create_user(self, username, passwd):
    # 获取或者新建User
    return user

不想自己写的话,django与flask都有现成的库:

  • django-ldap
  • flask-ldap

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python Web开发模板引擎优缺点总结
May 06 Python
Python中的defaultdict模块和namedtuple模块的简单入门指南
Apr 01 Python
python获取mp3文件信息的方法
Jun 15 Python
Python基于辗转相除法求解最大公约数的方法示例
Apr 04 Python
利用arcgis的python读取要素的X,Y方法
Dec 22 Python
Python实现爬取马云的微博功能示例
Feb 16 Python
Python地图绘制实操详解
Mar 04 Python
python中import与from方法总结(推荐)
Mar 21 Python
Python+threading模块对单个接口进行并发测试
Jun 25 Python
Python常用类型转换实现代码实例
Jul 28 Python
Django怎么在admin后台注册数据库表
Nov 14 Python
如何创建一个Flask项目并进行简单配置
Nov 18 Python
Python OpenCV中的resize()函数的使用
Jun 20 #Python
python中的句柄操作的方法示例
Jun 20 #Python
使用python获取(宜宾市地震信息)地震信息
Jun 20 #Python
一篇文章了解Python中常见的序列化操作
Jun 20 #Python
python集合是否可变总结
Jun 20 #Python
Django如何自定义model创建数据库索引的顺序
Jun 20 #Python
pyqt 多窗口之间的相互调用方法
Jun 19 #Python
You might like
PHP检测链接是否存在的代码实例分享
2016/05/06 PHP
解决Laravel自定义类引入和命名空间的问题
2019/10/15 PHP
自适应图片大小的弹出窗口
2006/07/27 Javascript
javascript 面向对象编程基础:封装
2009/08/21 Javascript
jquery导航制件jquery鼠标经过变色效果示例
2013/12/05 Javascript
学习JavaScript设计模式之代理模式
2016/01/12 Javascript
jquery mobile 实现自定义confirm确认框效果的简单实例
2016/06/17 Javascript
解析JavaScript模仿块级作用域
2016/12/29 Javascript
jQuery实现的form转json经典示例
2017/10/10 jQuery
nodejs微信扫码支付功能实现
2018/02/17 NodeJs
Vue项目全局配置页面缓存之按需读取缓存的实现详解
2018/08/01 Javascript
使用Node搭建reactSSR服务端渲染架构
2018/08/30 Javascript
Vue文件配置全局变量的实例
2018/09/06 Javascript
vue中接口域名配置为全局变量的实现方法
2018/09/20 Javascript
Python字符串的encode与decode研究心得乱码问题解决方法
2009/03/23 Python
python开发的小球完全弹性碰撞游戏代码
2013/10/15 Python
python实现目录树生成示例
2014/03/28 Python
Python批量按比例缩小图片脚本分享
2015/05/21 Python
Python对数据库操作
2016/03/28 Python
Python标准库之itertools库的使用方法
2017/09/07 Python
python生成带有表格的图片实例
2019/02/03 Python
对pyqt5中QTabWidget的相关操作详解
2019/06/21 Python
如何使用django的MTV开发模式返回一个网页
2019/07/22 Python
Python爬虫 bilibili视频弹幕提取过程详解
2019/07/31 Python
Python中输入和输出(打印)数据实例方法
2019/10/13 Python
使用Tensorflow实现可视化中间层和卷积层
2020/01/24 Python
玩转CSS3色彩
2010/01/16 HTML / CSS
详解css3中 text-fill-color属性
2019/07/08 HTML / CSS
涂鸦板简单实现 Html5编写属于自己的画画板
2016/07/05 HTML / CSS
html5本地存储_动力节点Java学院整理
2017/07/12 HTML / CSS
HTML5中5个简单实用的API(第二篇,含全屏、可见性、拍照、预加载、电池状态)
2014/05/07 HTML / CSS
新奥尔良珠宝:Mignon Faget
2020/11/23 全球购物
创建市级文明单位实施方案
2014/03/01 职场文书
民主生活会对照检查材料
2014/09/22 职场文书
参观监狱警示教育心得体会
2016/01/15 职场文书
Mysql 性能监控及调优
2021/04/06 MySQL