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中的yield函数的用法
Apr 03 Python
通过5个知识点轻松搞定Python的作用域
Sep 09 Python
Python 爬虫学习笔记之多线程爬虫
Sep 21 Python
Python实现的视频播放器功能完整示例
Feb 01 Python
Python之读取TXT文件的方法小结
Apr 27 Python
对python 数据处理中的LabelEncoder 和 OneHotEncoder详解
Jul 11 Python
django项目搭建与Session使用详解
Oct 10 Python
Python中正则表达式的用法总结
Feb 22 Python
python实现输入任意一个大写字母生成金字塔的示例
Oct 27 Python
PyTorch使用cpu加载模型运算方式
Jan 13 Python
计算pytorch标准化(Normalize)所需要数据集的均值和方差实例
Jan 15 Python
Django生成数据库及添加用户报错解决方案
Oct 09 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 图像尺寸调整代码
2010/05/26 PHP
php 生成文字png图片的代码
2011/04/17 PHP
Codeigniter(CI)框架分页函数及相关知识
2014/11/03 PHP
php写一个函数,实现扫描并打印出自定目录下(含子目录)所有jpg文件名
2017/05/26 PHP
Javascript里使用Dom操作Xml
2006/09/20 Javascript
vs2003 js文件编码问题的解决方法
2010/03/20 Javascript
Javascript this 的一些学习总结
2012/08/31 Javascript
javascript检测页面是否缩放的小例子
2013/05/16 Javascript
js中call与apply的用法小结
2013/12/28 Javascript
详解Angular2中的编程对象Observable
2016/09/17 Javascript
前端设计师们最常用的JS代码汇总
2016/09/25 Javascript
JavaScript中Require调用js的实例分享
2017/10/27 Javascript
JavaScript实现的DOM树遍历方法详解【二叉DOM树、多叉DOM树】
2018/05/07 Javascript
深入浅析Vue全局组件与局部组件的区别
2018/06/15 Javascript
详解webpack+ES6+Sass搭建多页面应用
2018/11/05 Javascript
vue+element-ui表格封装tag标签使用插槽
2020/06/18 Javascript
python代码制作configure文件示例
2014/07/28 Python
python脚本内运行linux命令的方法
2015/07/02 Python
使用Python爬取最好大学网大学排名
2018/02/24 Python
解决Django中调用keras的模型出现的问题
2019/08/07 Python
PyTorch的SoftMax交叉熵损失和梯度用法
2020/01/15 Python
如何利用python之wxpy模块玩转微信
2020/08/17 Python
日本PLST在线商店:日本时尚杂志刊载的人气服装
2016/12/10 全球购物
如何写一个自定义标签
2012/12/28 面试题
关键字throw与throws的用法差异
2016/11/22 面试题
高中生家长会演讲稿
2014/01/14 职场文书
小学生家长寄语
2014/04/02 职场文书
质量保证书范本
2014/04/29 职场文书
出国英文推荐信
2014/05/10 职场文书
文明班集体申报材料
2014/05/23 职场文书
2014年创先争优工作总结
2014/12/11 职场文书
2015年清明节活动总结
2015/02/09 职场文书
滴水洞导游词
2015/02/10 职场文书
小程序wx.getUserProfile接口的具体使用
2021/06/02 Javascript
详解Python requests模块
2021/06/21 Python
如何解决flex文本溢出问题小结
2022/07/15 HTML / CSS