Django集成LDAP身份验证完整指南
本文详细介绍如何在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:
- 方式一:使用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。
- 方式二:使用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。
- 利用第2步生成的DN值与用户密码尝试访问LDAP系统,若访问成功则验证通过,否则验证失败。
基本配置参数说明:
- AUTH_LDAP_SERVER_URI:指定LDAP服务器的地址及端口号。
- AUTH_LDAP_BIND_DN, AUTH_LDAP_BIND_PASSWORD:用于查找用户及相关信息的默认绑定用户凭证。
- AUTH_LDAP_USER_SEARCH:第一个参数指定查询目录,第三个参数为过滤条件(过滤条件可非常复杂,具体需查阅相关文档)。
- AUTH_LDAP_USER_DN_TEMPLATE:用户DN模板。配置此参数后,django-auth-ldap将使用生成的DN配合密码验证该用户。
- AUTH_LDAP_USER_ATTR_MAP:定义LDAP属性与Django User模型字段的映射关系。
- 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()
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













