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中的应用之translate和maketrans用法详解
Aug 27 Python
Python cookbook(数据结构与算法)字典相关计算问题示例
Feb 18 Python
python实现连续图文识别
Dec 18 Python
Django框架模板介绍
Jan 15 Python
Python第三方库face_recognition在windows上的安装过程
May 03 Python
Python实现基于socket的udp传输与接收功能详解
Nov 15 Python
python如何获取apk的packagename和activity
Jan 10 Python
解决python replace函数替换无效问题
Jan 18 Python
解决pymysql cursor.fetchall() 获取不到数据的问题
May 15 Python
Python利用Xpath选择器爬取京东网商品信息
Jun 01 Python
Python3通过chmod修改目录或文件权限的方法示例
Jun 08 Python
python urllib库的使用详解
Apr 13 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分页的功能模块
2015/06/16 PHP
如何解决PHP使用mysql_query查询超大结果集超内存问题
2016/03/14 PHP
Yii2中datetime类的使用
2016/12/17 PHP
PHP实现微信图片上传到服务器的方法示例
2017/06/29 PHP
thinkphp3.2嵌入百度编辑器ueditor的实例代码
2017/07/13 PHP
Javascript与vbscript数据共享
2007/01/09 Javascript
锋利的jQuery 要点归纳(三) jQuery中的事件和动画(上:事件篇)
2010/03/24 Javascript
jQuery应用之jQuery链用法实例
2015/01/19 Javascript
12行javascript代码绘制一个八卦图
2015/04/02 Javascript
JS打字效果的动态菜单代码分享
2015/08/21 Javascript
jQuery实现点击任意位置弹出层外关闭弹出层效果
2016/10/19 Javascript
关于AngularJs数据的本地存储详解
2017/01/20 Javascript
JavaScript下拉菜单功能实例代码
2017/03/01 Javascript
jQuery使用$.extend(true,object1, object2);实现深拷贝对象的方法分析
2019/03/06 jQuery
移动端JS实现拖拽两种方法解析
2020/10/12 Javascript
[54:19]完美世界DOTA2联赛PWL S2 Magma vs PXG 第二场 11.28
2020/12/01 DOTA
Python素数检测实例分析
2015/06/15 Python
python操作字典类型的常用方法(推荐)
2016/05/16 Python
python 3.5下xadmin的使用及修复源码bug
2017/05/10 Python
python实现汽车管理系统
2018/11/30 Python
python实现将两个文件夹合并至另一个文件夹(制作数据集)
2020/04/03 Python
解决python图像处理图像赋值后变为白色的问题
2020/06/04 Python
详解Windows下PyCharm安装Numpy包及无法安装问题解决方案
2020/06/18 Python
Python-split()函数实例用法讲解
2020/12/18 Python
如何查看python关键字
2021/01/17 Python
三只松鼠官方旗舰店:全网坚果销售第1
2017/11/25 全球购物
美国领先的家庭智能音响系统品牌:Sonos
2018/07/20 全球购物
美国CVS药店官网:CVS Pharmacy
2018/07/26 全球购物
英国领先的在线高尔夫设备零售商:Golfgeardirect
2020/12/11 全球购物
初三家长会邀请函
2014/01/18 职场文书
《黄河颂》教学反思
2014/02/07 职场文书
我爱读书演讲稿
2014/05/07 职场文书
新教师个人工作总结
2015/02/06 职场文书
答谢酒会主持词
2015/07/02 职场文书
解读Vue组件注册方式
2021/05/15 Vue.js
Python+Appium自动化测试的实战
2021/06/30 Python