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算法之栈(stack)的实现
Aug 18 Python
利用Python绘制数据的瀑布图的教程
Apr 07 Python
Python导出数据到Excel可读取的CSV文件的方法
May 12 Python
pycharm设置注释颜色的方法
May 23 Python
pip install urllib2不能安装的解决方法
Jun 12 Python
python文件操作之批量修改文件后缀名的方法
Aug 10 Python
python+openCV利用摄像头实现人员活动检测
Jun 22 Python
解决Python计算矩阵乘向量,矩阵乘实数的一些小错误
Aug 26 Python
Python处理session的方法整理
Aug 29 Python
Python爬虫实例——爬取美团美食数据
Jul 15 Python
PyQT5速成教程之Qt Designer介绍与入门
Nov 02 Python
python 爬取哔哩哔哩up主信息和投稿视频
Jun 07 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
对Session和Cookie的区分与解释
2007/03/16 PHP
PHP5常用函数列表(分享)
2013/06/07 PHP
ThinkPHP分页类使用详解
2014/03/05 PHP
php以fastCGI的方式运行时文件系统权限问题及解决方法
2015/05/11 PHP
利用php-cli和任务计划实现订单同步功能的方法
2017/05/03 PHP
ext combobox动态加载数据库数据(附前后台)
2014/06/17 Javascript
javascript搜索框点击文字消失失焦时文本出现
2014/09/18 Javascript
js创建jsonArray传输至后台及后台全面解析
2016/04/11 Javascript
Bootstrap弹出框modal上层的输入框不能获得焦点问题的解决方法
2016/12/13 Javascript
新闻上下滚动jquery 超简洁(必看篇)
2017/01/21 Javascript
JavaScript在form表单中使用button按钮实现submit提交方法
2017/01/23 Javascript
nodejs入门教程四:URL相关模块用法分析
2017/04/24 NodeJs
浅谈vue实现数据监听的函数 Object.defineProperty
2017/06/08 Javascript
Vue-cli 使用json server在本地模拟请求数据的示例代码
2017/11/02 Javascript
vue 权限认证token的实现方法
2018/07/17 Javascript
Layui 设置select下拉框自动选中某项的方法
2018/08/14 Javascript
详解Vue组件插槽的使用以及调用组件内的方法
2018/11/13 Javascript
浅谈Webpack多页应用HMR卡住问题
2019/04/24 Javascript
深入浅出了解Node.js Streams
2019/05/27 Javascript
你可能从未使用过的11+个JavaScript特性(小结)
2020/01/08 Javascript
vue中实现回车键登录功能
2020/02/19 Javascript
[01:06]DOTA2小知识课堂 Ep.02 吹风竟可解梦境缠绕
2019/12/05 DOTA
[42:23]完美世界DOTA2联赛PWL S3 Forest vs Rebirth 第二场 12.10
2020/12/13 DOTA
Python性能优化的20条建议
2014/10/25 Python
python getopt详解及简单实例
2016/12/30 Python
深入了解Python中pop和remove的使用方法
2018/01/09 Python
python列表生成式与列表生成器的使用
2018/02/23 Python
python,Django实现的淘宝客登录功能示例
2019/06/12 Python
py-charm延长试用期限实例
2019/12/22 Python
对pytorch的函数中的group参数的作用介绍
2020/02/18 Python
美国购买舞会礼服网站:Couture Candy
2019/12/29 全球购物
为什么group by 和order by会使查询变慢
2014/05/16 面试题
爱牙日宣传活动总结
2015/02/05 职场文书
校园安全教育心得体会
2016/01/15 职场文书
在JavaScript中如何使用宏详解
2021/05/06 Javascript
python 实现体质指数BMI计算
2021/05/26 Python