Python LDAP3双问题:AD用户名认证失败与多域User对象创建
技术问题咨询
1. LDAP认证问题
当前使用django-python3-ldap配置可通过邮箱地址完成认证,但无法使用AD用户名认证。已将LDAP_AUTH_USER_FIELDS中的"username": "mail"修改为"username": "sAMAccountName",也尝试过"uid",均无效,请问原因是什么?
配置代码:
LDAP_AUTH_URL = "ldap://some_address" LDAP_AUTH_FORMAT_USERNAME = "django_python3_ldap.utils.format_username_active_directory" LDAP_AUTH_SEARCH_BASE = "dc=various_dc_values,dc=com" LDAP_AUTH_OBJECT_CLASS = 'Person' LDAP_AUTH_USER_FIELDS = { "username": "mail", "first_name": "givenName", "last_name": "sn", "email": "mail", }
问题分析与解决思路
- 用户名格式化不匹配:
format_username_active_directory默认会把用户名格式化为DOMAIN\username,如果你的AD环境不需要该前缀或前缀错误,会导致LDAP搜索失败。可以自定义格式化函数直接返回原始用户名:def custom_format_username(username): return username LDAP_AUTH_FORMAT_USERNAME = "your_project.utils.custom_format_username" - 搜索过滤器未同步修改:django-python3-ldap默认搜索过滤器基于
username对应的LDAP属性,修改映射后需显式指定匹配sAMAccountName的过滤器:LDAP_AUTH_SEARCH_FILTER = "(sAMAccountName=%(user)s)" - LDAP权限与属性有效性:确认LDAP绑定账号有读取用户
sAMAccountName属性的权限,同时检查AD用户的sAMAccountName属性是否存在有效值(注意区分大小写)。 - 用户查找字段配置:确保
LDAP_AUTH_USER_LOOKUP_FIELDS设置正确,让本地用户查找时匹配sAMAccountName:LDAP_AUTH_USER_LOOKUP_FIELDS = ("username",)
2. 多域认证下User对象创建问题
希望实现多域认证,因无法在配置文件中添加其他域,故自定义了认证函数。但创建User对象时遇到问题,具体代码如下:
# 用后端认证用户 # 认证成功会返回带姓名信息的User对象,供模板调用 user = auth.authenticate(username=email, password=password) # 判断是否认证失败,或用户属于其他域 if user is None: # 尝试创建新User对象,但这行不符合预期,我需要一个可用于认证的空白User实例 user = django_apps.get_model(settings.AUTH_USER_MODEL, require_ready=False) # 用其他域认证用户 # 原本预期认证后request会带上姓名信息 TryOtherAuthentication( email, password, request) # 此处报错:'AnonymousUser' object has no attribute 'first_name' user.first_name = request.user.first_name user.last_name = request.user.last_name user.is_staff = request.user.is_staff user.save()
已知跨域认证函数TryOtherAuthentication可正常返回用户信息(姓名、权限等),但当前代码报错“'AnonymousUser' object has no attribute 'first_name'”,且无法创建可正常登录的User对象以跳转到首页(使用auth.login(request, user)和redirect('index'))。当User对象由后端认证返回时,如下代码可正常运行:
user.first_name = 'Bugsy' user.last_name = 'Malone' user.save()
问题分析与解决思路
- 错误实例化User对象:
django_apps.get_model(...)返回的是User模型类,不是实例,需要先创建实例才能设置属性:UserModel = django_apps.get_model(settings.AUTH_USER_MODEL, require_ready=False) user = UserModel() - request.user未被正确赋值:
TryOtherAuthentication执行后request.user仍是AnonymousUser,因为还未完成登录流程。应修改该函数让它返回认证成功的用户信息字典,而非直接操作request:# 修改TryOtherAuthentication,返回包含用户信息的字典 user_info = TryOtherAuthentication(email, password) if user_info: # 创建User实例(username可根据需求用AD用户名或邮箱) user = UserModel.objects.create( username=email, email=email, first_name=user_info['first_name'], last_name=user_info['last_name'], is_staff=user_info['is_staff'] ) # 多域认证无需本地密码,设置为不可用密码 user.set_unusable_password() user.save() # 完成登录流程,让request.user指向该实例 auth.login(request, user) - 确保登录流程完整:创建User实例后必须调用
auth.login(request, user),才能让用户处于登录状态,后续才能正常访问用户属性并跳转首页。
内容的提问来源于stack exchange,提问作者Clandestine
相关产品推荐
相关产品推荐

