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 fileinput模块使用介绍
Nov 30 Python
Python2中的raw_input() 与 input()
Jun 12 Python
Django中使用locals()函数的技巧
Jul 16 Python
python之virtualenv的简单使用方法(必看篇)
Nov 25 Python
Django学习笔记之ORM基础教程
Mar 27 Python
Ubuntu下使用Python实现游戏制作中的切分图片功能
Mar 30 Python
python 数字类型和字符串类型的相互转换实例
Jul 17 Python
python bmp转换为jpg 并删除原图的方法
Oct 25 Python
简单了解python数组的基本操作
Nov 26 Python
Python中使用gflags实例及原理解析
Dec 13 Python
详解Python3中的 input() 函数
Mar 18 Python
python用tkinter实现一个简易能进行随机点名的界面
Sep 27 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
解决dede生成静态页和动态页转换的一些问题,及火车采集入库生成动态的办法
2007/03/29 PHP
wordpress之js库集合研究介绍
2007/08/17 Javascript
JQuery动态给table添加、删除行 改进版
2011/01/19 Javascript
jquery实现鼠标滑过小图时显示大图的方法
2015/01/14 Javascript
JavaScript Date 知识浅析
2017/01/29 Javascript
jQuery Ajax全解析
2017/02/13 Javascript
超级简易的JS计算器实例讲解(实现加减乘除)
2017/08/08 Javascript
关于ES6箭头函数中的this问题
2018/02/27 Javascript
解决vue中无法动态修改jqgrid组件 url地址的问题
2018/03/01 Javascript
JavaScript函数apply()和call()用法与异同分析
2018/08/10 Javascript
vue在手机中通过本机IP地址访问webApp的方法
2018/08/15 Javascript
vue 实现小程序或商品秒杀倒计时
2019/04/14 Javascript
javascript实现简易数码时钟
2020/03/30 Javascript
Vue列表如何实现滚动到指定位置样式改变效果
2020/05/09 Javascript
在vue中实现echarts随窗体变化
2020/07/27 Javascript
vue 实现element-ui中的加载中状态
2020/11/11 Javascript
python使用xlrd和xlwt读写Excel文件的实例代码
2018/09/05 Python
pymongo中聚合查询的使用方法
2019/03/22 Python
VPS CENTOS 上配置python,mysql,nginx,uwsgi,django的方法详解
2019/07/01 Python
Python qqbot 实现qq机器人的示例代码
2019/07/11 Python
详解python实现小波变换的一个简单例子
2019/07/18 Python
使用Python实现文字转语音并生成wav文件的例子
2019/08/08 Python
Python3基本输入与输出操作实例分析
2020/02/14 Python
python删除文件、清空目录的实现方法
2020/09/23 Python
CSS3 Pie工具推荐--让IE6-8支持一些优秀的CSS3特性
2014/09/02 HTML / CSS
HTML5新增元素如何兼容旧浏览器有哪些方法
2014/05/09 HTML / CSS
将"引用"作为函数返回值类型的格式、好处和需要遵守的规则
2016/02/09 面试题
Ajax主要包含了哪些技术
2014/06/12 面试题
党的群众路线教育实践活动心得体会
2014/03/03 职场文书
学习型党组织心得体会
2014/09/12 职场文书
党员干部三严三实心得体会
2014/10/13 职场文书
师范生见习总结范文
2015/06/23 职场文书
师范生见习自我总结
2015/06/23 职场文书
创业计划书之宠物店
2019/09/19 职场文书
简单介绍Python的第三方库yaml
2021/06/18 Python
Django REST framework 限流功能的使用
2021/06/24 Python