Django集成LDAP身份验证完整指南

江屿
江屿
发布时间:2026-10-13 | 6人浏览过
原创

本文详细介绍如何在Django项目中集成LDAP进行用户身份验证。涵盖python_ldap与django-auth-ldap的安装配置,settings.py核心参数解析(如AUTH_LDAP_SERVER_URI、USER_DN_TEMPLATE),以及用户组同步、中文乱码处理等常见问题解决方案,帮助开发者实现基于AD/LDAP的统一认证管理。

首先安装Python-LDAP库,具体命令为:pip install python_ldap-2.4.25-cp27-none-win_amd64.whl。

接着安装django-auth-ldap,文件名为django-auth-ldap-1.2.8.tar.gz(下载地址:https://pypi.python.org/pypi/django-auth-ldap)。在Windows环境下,也可以执行python setup.py install进行安装。

安装完成后,运行相关命令验证,若执行成功则表明安装无误。

from django_auth_ldap.config import LDAPSearch, LDAPSearchUnion, GroupOfNamesType 

随后配置settings.py文件,添加以下配置项:

详细配置参考:https://pypi.python.org/pypi/django-auth-ldap/1.2.1的官方说明文档。

# -*- coding: UTF-8 -*-

import ldap
from django_auth_ldap.config import LDAPSearch #导入LDAP model

AUTHENTICATION_BACKENDS = ( 
  'django_auth_ldap.backend.LDAPBackend', #配置为先使用LDAP认证,如通过认证则不再使用后面的认证方式
  'django.contrib.auth.backends.ModelBackend', 
) 

AUTH_LDAP_SERVER_URI = 'ldap://192.168.200.20:389'
AUTH_LDAP_BIND_DN = 'CN=test01,OU=ServerAdmin,DC=uu,DC=yyy,DC=com'
AUTH_LDAP_BIND_PASSWORD = '123456' 
OU = unicode('OU=中文名,DC=uu,DC=yyy,DC=com', 'utf8') #限制哪个OU中的用户可以进行AD认证。如果OU中包含有中文字符,则需要这样写,否则会出现ascii无法识别的报错(UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position)
# OU0 = 'OU=ServerAdmin,DC=uxin,DC=youxinpai,DC=com'
# OU = unicode('OU=优,DC=uxin,DC=youxinpai,DC=com', 'utf8')
# OU1 = u'OU=优,DC=uxin,DC=youxinpai,DC=com'
# OU2 = u'OU=\u4f18,DC=uxin,DC=youxinpai,DC=com'
# OU == OU1 == OU2 #返回True
#检索单个OU
AUTH_LDAP_USER_SEARCH = LDAPSearch(OU, ldap.SCOPE_SUBTREE, "(&(objectClass=person)(sAMAccountName=%(user)s))")

# 检索多个OU:
# AUTH_LDAP_USER_SEARCH = LDAPSearchUnion( 
#   LDAPSearch("ou=user,ou=ou1,ou=ou,dc=cn,dc=com",ldap.SCOPE_SUBTREE, "(&(objectClass=user)(sAMAccountName=%(user)s))"), 
#   LDAPSearch("ou=user,ou=ou2,ou=ou,dc=cn,dc=com",ldap.SCOPE_SUBTREE, "(&(objectClass=user)(sAMAccountName=%(user)s))"), 
# ) 

#将账号的姓、名、邮件地址保存到django的auth_user表中,在admin后台可以看到
AUTH_LDAP_USER_ATTR_MAP = { 
  "first_name": "givenName",
  "last_name": "sn",
  "email": "mail"
} 

关于同步用户组信息:

当用户成功登录后,若该用户属于特定组,系统会将该组信息同步至auth_group表中。此后,管理员可在后台对该组进行权限设置,同组用户登录后即自动获得相应权限。

若某用户不再属于某个组,该组记录不会自动删除,需管理员在后台手动移除。

from django_auth_ldap.config import LDAPSearch, LDAPSearchUnion, GroupOfNamesType 

AUTH_LDAP_GROUP_TYPE = GroupOfNamesType(name_attr="cn") #返回的组的类型,并用来判断用户与组的从属关系

OUg = unicode('OU=安全组,DC=uu,DC=yyy,DC=com', 'utf8')
AUTH_LDAP_GROUP_SEARCH = LDAPSearch(OUg,ldap.SCOPE_SUBTREE, "(objectClass=group)" ) #搜索某个OU下组信息
 
AUTH_LDAP_MIRROR_GROUPS = True #导入用户的组信息,在用户登录的时候把用户的域组关系同步过来。每次用户登录时,都会把用户的组关系删除,重新从ldap中进行同步(解决办法参考后面)

AUTH_LDAP_ALWAYS_UPDATE_USER = True #是否同步LDAP修改

编辑views.py,用户通过LDAP认证后,可继续使用Django自带的用户认证及权限管理模块:

from django.contrib.auth import authenticate,login as auth_login,logout as auth_logout
from django.contrib.auth.models import User

@csrf_exempt
def loginauth(request):
  user_loggedin='Guest'
  errors_list=[]
  if request.method == 'POST':
    print 'pp: ',request.POST.get('name'),request.POST.get('password')
    name = request.POST.get('name')
    password = request.POST.get('password')
    user = authenticate(username=name, password=password)
    print 'authuser',user
    if user is not None:
      auth_login(request,user)
      uu=request.user
      u=User.objects.get(username=uu)return HttpResponseRedirect("../check_dict")
    
  context={'errors_list':errors_list,'user_loggedin':user_loggedin}
  return render(request,'aptest/loginauth.html',context)

auth_user表结构如下:

 

Admin后台显示效果:

 

解决中文乱码问题(如遇问题可尝试此方法):

在安装django-auth-ldap-1.2.8.tar之前,需先打开其中的.py文件,并在头部添加'# -*- coding: UTF-8 -*-'声明。

修改C:\Python27\Lib\site-packages\Django-1.8.4-py2.7.egg\django\conf\global_settings.py以及项目的settings.py,配置如下:

TIME_ZONE = 'Asia/Shanghai'
LANGUAGE_CODE = 'zh-hans'

======================== ========================

LDAP用户验证基本原理:

LDAP系统中每个用户拥有唯一的DN(Distinguished Name)值。例如,配置文件中默认的admin用户在LDAP中的DN为uid=admin,ou=system,dc=eoncloud,dc=com,其中eoncloud.com为域名,system为组织单位(组名),admin为用户名。部分LDAP系统使用cn而非uid生成DN,此时admin的DN可能显示为cn=admin,ou=system,dc=eoncloud,dc=com。无论前缀是uid、cn还是其他,django-ldap-auth均使用DN来验证用户身份并获取用户信息。

假设用户输入的账号及密码为:test, password。

django-auth-ldap提供2种方式获取用户的DN:

  1. 方式一:使用AUTH_LDAP_USER_DN_TEMPLATE提供的模板生成DN。例如配置uid=%(user)s,ou=users,dc=eoncloud,dc=com,其中%(user)s会被替换为实际用户名,最终生成的DN即为uid=test,ou=users,dc=eonclooud,dc=com。
  2. 方式二:使用AUTH_LDAP_GROUP_SEARCH。若未配置AUTH_LDAP_USER_DN_TEMPLATE,系统将根据AUTH_LDAP_BIND_DN和AUTH_LDAP_BIND_PASSWORD提供的DN与密码,结合AUTH_LDAP_GROUP_SEARCH指定的查询条件搜索test用户。若未找到用户,则验证失败;若找到用户,则使用返回数据生成test的DN。
  3. 利用第2步生成的DN值与用户密码尝试访问LDAP系统,若访问成功则验证通过,否则验证失败。

基本配置参数说明:

  1. AUTH_LDAP_SERVER_URI:指定LDAP服务器的地址及端口号。
  2. AUTH_LDAP_BIND_DN, AUTH_LDAP_BIND_PASSWORD:用于查找用户及相关信息的默认绑定用户凭证。
  3. AUTH_LDAP_USER_SEARCH:第一个参数指定查询目录,第三个参数为过滤条件(过滤条件可非常复杂,具体需查阅相关文档)。
  4. AUTH_LDAP_USER_DN_TEMPLATE:用户DN模板。配置此参数后,django-auth-ldap将使用生成的DN配合密码验证该用户。
  5. AUTH_LDAP_USER_ATTR_MAP:定义LDAP属性与Django User模型字段的映射关系。
  6. AUTH_LDAP_ALWAYS_UPDATE_USER:控制是否同步LDAP中的用户修改信息。

用户组配置:

如需从LDAP系统获取用户组信息,或限制/阻止特定组用户访问,需先配置组类型AUTH_LDAP_GROUP_TYPE及AUTH_LDAP_GROUP_SEARCH。由于LDAP中组的种类繁多,具体信息请查询相关资料。

AUTH_LDAP_GROUP_TYPE:

  • 值类型:LDAPGroupType的子类实例。LDAPGroupType包含2个初始化参数:member_attr(组成员属性名)和name_attr(组名称属性名)。
  • 作用:用于识别AUTH_LDAP_GROUP_SEARCH返回的组的类型,并判断用户与组的从属关系。

AUTH_LDAP_GROUP_SEARCH:

  • 值类型:LDAPSearch实例。
  • 作用:定义用户组的查询条件。

AUTH_LDAP_REQUIRE_GROUP:

  • 值类型:组的DN。
  • 作用:仅允许指定组的用户访问系统。

AUTH_LDAP_DENY_GROUP指定的:

  • 值类型:组的DN。
  • 作用:禁止指定组的用户访问系统。

AUTH_LDAP_MIRROR_GROUPS:

  • 值类型:bool值。
  • 作用:导入用户的组信息。

设置AUTH_LDAP_MIRROR_GROUPS=True旨在用户登录时获取并记录用户的域组关系。但开启此参数会引发一个问题:每次用户登录时,系统都会删除原有的组关系并重新从LDAP同步。由于系统中存在除域组外的自定义组关系,这会导致自定义组的用户关系无法持久保留。根据需求,通常仅在用户第一次登录时同步组关系,后续登录无需同步。此需求可通过微调django-auth-ldap源码(backend.py)实现。

backend.py源码修改示例:

def _get_or_create_user(self, force_populate=False): 
...
...
  if self.settings.MIRROR_GROUPS: 
    self._mirror_groups() 

#修改为如下,然后重新安装django-auth-ldap-1.2.8.tar,重启WEB重新验证即可。
  if self.settings.MIRROR_GROUPS and created: 
    self._mirror_groups() 

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表