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中运行并行任务技巧
Feb 26 Python
简单掌握Python的Collections模块中counter结构的用法
Jul 07 Python
Python正则表达式教程之三:贪婪/非贪婪特性
Mar 02 Python
Python基于回溯法子集树模板解决野人与传教士问题示例
Sep 11 Python
详解在python操作数据库中游标的使用方法
Nov 12 Python
Python爬取腾讯视频评论的思路详解
Dec 19 Python
pytorch torch.nn.AdaptiveAvgPool2d()自适应平均池化函数详解
Jan 03 Python
python numpy矩阵信息说明,shape,size,dtype
May 22 Python
Keras 实现加载预训练模型并冻结网络的层
Jun 15 Python
浅谈TensorFlow中读取图像数据的三种方式
Jun 30 Python
如何使用Django Admin管理后台导入CSV
Nov 06 Python
Python爬虫之爬取某文库文档数据
Apr 21 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
真正面向对象编程:PHP5.01发布
2006/10/09 PHP
PHP5中的时间相差8小时的解决办法
2008/03/28 PHP
备份mysql数据库的php代码(一个表一个文件)
2010/05/28 PHP
thinkphp控制器调度使用示例
2014/02/24 PHP
WordPres对前端页面调试时的两个PHP函数使用小技巧
2015/12/22 PHP
php微信开发之上传临时素材
2016/06/24 PHP
PHP中仿制 ecshop验证码实例
2017/01/06 PHP
PHP实现的Redis多库选择功能单例类
2017/07/27 PHP
javascript Array.prototype.slice使用说明
2010/10/11 Javascript
JavaScript-RegExp对象只能使用一次问题解决方法
2014/06/23 Javascript
jQuery幻灯片特效代码分享--鼠标滑过按钮时切换(2)
2020/11/18 Javascript
实例讲解避免javascript冲突的方法
2016/01/03 Javascript
javascript先序遍历DOM树的方法
2016/02/27 Javascript
vue脚手架vue-cli的学习使用教程
2017/06/06 Javascript
JS获取并处理php数组的方法实例分析
2018/09/04 Javascript
详解vue项目中调用百度地图API使用方法
2019/04/25 Javascript
微信小程序 授权登录详解(附完整源码)
2019/08/23 Javascript
[37:03]完美世界DOTA2联赛PWL S3 INK ICE vs GXR 第二场 12.16
2020/12/18 DOTA
Python+Django在windows下的开发环境配置图解
2009/11/11 Python
python list中append()与extend()用法分享
2013/03/24 Python
python实现根据ip地址反向查找主机名称的方法
2015/04/29 Python
python爬取网易云音乐评论
2018/11/16 Python
python程序封装为win32服务的方法
2021/03/07 Python
在Django下创建项目以及设置settings.py教程
2019/12/03 Python
python飞机大战pygame游戏框架搭建操作详解
2019/12/17 Python
Python找出列表中出现次数最多的元素三种方式
2020/02/24 Python
python中sklearn的pipeline模块实例详解
2020/05/21 Python
Django实现后台上传并显示图片功能
2020/05/29 Python
python 星号(*)的多种用途
2020/09/21 Python
Python爬虫抓取论坛关键字过程解析
2020/10/19 Python
车辆维修工自我评价怎么写
2013/09/20 职场文书
精彩的大学生自我评价
2013/11/17 职场文书
母亲节演讲稿范文
2014/01/02 职场文书
民事诉讼授权委托书范文
2014/08/02 职场文书
民主评议党员自我鉴定
2014/10/21 职场文书
Spring Data JPA的Audit功能审计数据库的变更
2021/06/26 Java/Android