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中map、any、all函数用法分析
Apr 21 Python
Python通过命令开启http.server服务器的方法
Nov 04 Python
python 删除指定时间间隔之前的文件实例
Apr 24 Python
Python排序算法之选择排序定义与用法示例
Apr 29 Python
Sanic框架应用部署方法详解
Jul 18 Python
Django 表单模型选择框如何使用分组
May 16 Python
python使用装饰器作日志处理的方法
Jul 11 Python
python:按行读入,排序然后输出的方法
Jul 20 Python
Python如何利用Har文件进行遍历指定字典替换提交的数据详解
Nov 05 Python
python3中确保枚举值代码分析
Dec 02 Python
Pandas直接读取sql脚本的方法
Jan 21 Python
Pytorch 中的optimizer使用说明
Mar 03 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
paypal即时到账php实现代码
2010/11/28 PHP
Memcached常用命令以及使用说明详解
2013/06/27 PHP
thinkphp获取栏目和文章当前位置的方法
2014/10/29 PHP
Gambit vs CL BO3 第二场 2.13
2021/03/10 DOTA
Javascript - HTML的request类
2006/07/15 Javascript
js实现目录定位正文示例
2013/11/14 Javascript
深入理解JavaScript中的传值与传引用
2013/12/09 Javascript
JQuery实现鼠标滚轮滑动到页面节点
2015/07/28 Javascript
Easyui form combobox省市区三级联动
2016/01/13 Javascript
js日期插件dateHelp获取本月、三个月、今年的日期
2016/03/07 Javascript
Bootstrap Paginator分页插件使用方法详解
2016/05/30 Javascript
JS调用打印机功能简单示例
2016/11/28 Javascript
Vue实现数字输入框中分割手机号码的示例
2017/10/10 Javascript
Vue实现内部组件轮播切换效果的示例代码
2018/04/07 Javascript
详解ECMAScript typeof用法
2018/07/25 Javascript
JS实现的冒泡排序,快速排序,插入排序算法示例
2019/03/02 Javascript
React实现评论的添加和删除
2020/10/20 Javascript
详解Python进程间通信之命名管道
2017/08/28 Python
Python实现简单的语音识别系统
2017/12/13 Python
对于Python深浅拷贝的理解
2019/07/29 Python
对Python中 \r, \n, \r\n的彻底理解
2020/03/06 Python
屏蔽Django admin界面添加按钮的操作
2020/03/11 Python
python 实现网易邮箱邮件阅读和删除的辅助小脚本
2021/03/01 Python
智能旅行箱:Horizn Studios
2018/04/30 全球购物
请用Python写一个获取用户输入数字,并根据数字大小输出不同信息的脚本
2014/05/20 面试题
如何从一个文件档案的尾端新增记录
2016/12/02 面试题
怎样声明一个匿名的内部类
2016/06/01 面试题
暑假实习求职信范文
2013/09/22 职场文书
幼儿园教师培训方案
2014/02/04 职场文书
cf战队收人广告词
2014/03/14 职场文书
企业宣传口号
2014/06/12 职场文书
房地产端午节活动方案
2014/08/24 职场文书
学校班子个人对照检查材料思想汇报
2014/09/27 职场文书
八月一日观后感
2015/06/10 职场文书
摘录式读书笔记
2015/07/01 职场文书
Python可视化神器pyecharts绘制水球图
2022/07/07 Python