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利用beautifulSoup实现爬虫
Sep 29 Python
python统计文本字符串里单词出现频率的方法
May 26 Python
Python学习笔记整理3之输入输出、python eval函数
Dec 14 Python
python入门前的第一课 python怎样入门
Mar 06 Python
Python函数any()和all()的用法及区别介绍
Sep 14 Python
手把手教你如何安装Pycharm(详细图文教程)
Nov 28 Python
将Python字符串生成PDF的实例代码详解
May 17 Python
利用python实现汉字转拼音的2种方法
Aug 12 Python
Python求解正态分布置信区间教程
Nov 20 Python
python第三方库学习笔记
Feb 07 Python
python 爬取腾讯视频评论的实现步骤
Feb 18 Python
python设置 matplotlib 正确显示中文的四种方式
May 10 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
使用Apache的htaccess防止图片被盗链的解决方法
2013/04/27 PHP
基于PHP+Ajax实现表单验证的详解
2013/06/25 PHP
php实现批量删除挂马文件及批量替换页面内容完整实例
2016/07/08 PHP
PHP实现QQ、微信和支付宝三合一收款码实例代码
2018/02/19 PHP
php实现微信公众平台发红包功能
2018/06/14 PHP
PHP通过get方法获得form表单数据方法总结
2018/09/12 PHP
Jquery实战_读书笔记1—选择jQuery
2010/01/22 Javascript
DOM Scripting中的图片切换[兼容Firefox]
2010/06/12 Javascript
js操作label给label赋值及取label的值示例
2013/11/07 Javascript
Node.js插件的正确编写方式
2014/08/03 Javascript
javascript解决IE6下hover问题的方法
2015/07/28 Javascript
jQuery实现垂直半透明手风琴特效代码分享
2015/08/21 Javascript
BootStrap智能表单实战系列(九)表单图片上传的支持
2016/06/13 Javascript
详解javascript事件绑定使用方法
2016/10/20 Javascript
JavaScript中String对象的方法介绍
2017/01/04 Javascript
详解vue-cli 构建Vue项目遇到的坑
2017/08/30 Javascript
JavaScript数据结构与算法之二叉树遍历算法详解【先序、中序、后序】
2019/02/21 Javascript
js神秘的电报密码 哈弗曼编码实现
2019/09/10 Javascript
jquery实现弹窗(系统提示框)效果
2019/12/10 jQuery
jQuery实现简单飞机大战
2020/07/05 jQuery
Python最基本的数据类型以及对元组的介绍
2015/04/14 Python
在Python的Tornado框架中实现简单的在线代理的教程
2015/05/02 Python
Python实现获取磁盘剩余空间的2种方法
2017/06/07 Python
Python 使用with上下文实现计时功能
2018/03/09 Python
python定时按日期备份MySQL数据并压缩
2019/04/19 Python
查看端口并杀进程python脚本代码
2019/12/17 Python
Python新手如何理解循环加载模块
2020/05/29 Python
CSS3中的弹性布局em运用入门详解 1em等于多少像素
2021/02/08 HTML / CSS
教师简历自我评价
2014/02/03 职场文书
企业办公室岗位职责
2014/03/12 职场文书
领导干部廉政承诺书
2014/03/27 职场文书
学校教师读书活动总结
2014/07/08 职场文书
2014机关干部学习“焦裕禄精神”思想汇报
2014/09/19 职场文书
商务考察邀请函模板
2015/02/02 职场文书
小型婚礼主持词
2015/06/30 职场文书
Java 在线考试云平台的实现
2021/11/23 Java/Android