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 参数列表中的self 显式不等于冗余
Dec 01 Python
详解Python当中的字符串和编码
Apr 25 Python
Python中的自省(反射)详解
Jun 02 Python
Python中基本的日期时间处理的学习教程
Oct 16 Python
python利用urllib实现爬取京东网站商品图片的爬虫实例
Aug 24 Python
Python高级特性切片(Slice)操作详解
Sep 27 Python
Python玩转Excel的读写改实例
Feb 22 Python
python GUI实现小球满屏乱跑效果
May 09 Python
Python正则表达式急速入门(小结)
Dec 16 Python
jupyter 中文乱码设置编码格式 避免控制台输出的解决
Apr 20 Python
Python扫描端口的实现
Jan 25 Python
Python Pandas知识点之缺失值处理详解
May 11 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 5.0 Pear安装方法
2006/12/06 PHP
剖析 PHP 中的输出缓冲
2006/12/21 PHP
PHP 面向对象 final类与final方法
2010/05/05 PHP
PHP循环语句笔记(foreach,list)
2011/11/29 PHP
解析:php调用MsSQL存储过程使用内置RETVAL获取过程中的return值
2013/07/03 PHP
php递归遍历多维数组的方法
2015/04/18 PHP
php截取视频指定帧为图片
2016/05/16 PHP
PHP封装的分页类与简单用法示例
2019/02/25 PHP
PHP获取ttf格式文件字体名的方法示例
2019/03/06 PHP
一个判断email合法性的函数[非正则]
2008/12/09 Javascript
MooTools 1.2中的Drag.Move来实现拖放
2009/09/15 Javascript
通过jquery 获取URL参数并进行转码
2014/08/18 Javascript
简介JavaScript中Math.LOG10E属性的使用
2015/06/14 Javascript
JS实现状态栏跑马灯文字效果代码
2015/10/24 Javascript
JS实现为排序好的字符串找出重复行的方法
2016/03/02 Javascript
文件上传的几个示例分享【推荐】
2016/12/16 Javascript
Bootstrap下拉菜单Dropdowns的实现代码
2017/03/17 Javascript
JS基于设计模式中的单例模式(Singleton)实现封装对数据增删改查功能
2018/02/06 Javascript
nodejs处理tcp连接的核心流程
2021/02/26 NodeJs
使用Python简单的实现树莓派的WEB控制
2016/02/18 Python
Python实现将SQLite中的数据直接输出为CVS的方法示例
2017/07/13 Python
解决使用PyCharm时无法启动控制台的问题
2019/01/19 Python
python图形绘制奥运五环实例讲解
2019/09/14 Python
python os.path.isfile()因参数问题判断错误的解决
2019/11/29 Python
django自定义非主键自增字段类型详解(auto increment field)
2020/03/30 Python
如何在Win10系统使用Python3连接Hive
2020/10/15 Python
cookies应对python反爬虫知识点详解
2020/11/25 Python
css3边框_动力节点Java学院整理
2017/07/11 HTML / CSS
在家更换处方镜片:Lensabl
2019/05/01 全球购物
Clarks其乐鞋荷兰官网:Clarks荷兰
2019/07/05 全球购物
《愚公移山》教学反思
2014/02/20 职场文书
运动会标语
2014/06/21 职场文书
销售合作意向书范本
2015/05/08 职场文书
解决python存数据库速度太慢的问题
2021/04/23 Python
Nginx+Windows搭建域名访问环境的操作方法
2022/03/17 Servers
浅谈MySql update会锁定哪些范围的数据
2022/06/25 MySQL