Django自定义不区分大小写认证后端后仅小写密码可登录问题求助
问题排查及修复方案
1. 认证后端顺序错误
你当前settings.py中配置的AUTHENTICATION_BACKENDS顺序有误,Django会按列表顺序依次调用认证后端,排在前面的默认AllowAllUsersModelBackend是大小写敏感的,会优先匹配和数据库大小写完全一致的邮箱,匹配失败才会调用你自定义的大小写不敏感后端。
修复方法:调整顺序,将自定义后端放在第一位,无需保留默认后端特性的话可以直接删除:
AUTHENTICATION_BACKENDS = ( 'account.backends.CaseInsensitiveModelBackend', )
如果确实需要保留AllowAllUsersModelBackend的特性(允许未激活用户登录),调整顺序即可:
AUTHENTICATION_BACKENDS = ( 'account.backends.CaseInsensitiveModelBackend', 'django.contrib.auth.backends.AllowAllUsersModelBackend', )
2. 自定义认证后端冗余代码问题
你写的CaseInsensitiveModelBackend中,except块内的UserModel().set_password(password)是完全无效的代码:仅创建了一个临时的用户对象、设置密码后直接丢弃,没有任何实际作用,还会额外消耗性能。同时用户不存在时没有显式返回None,虽然Python默认会返回None,但代码可读性很差。
修复后的backends.py代码:
from django.contrib.auth import get_user_model from django.contrib.auth.backends import ModelBackend class CaseInsensitiveModelBackend(ModelBackend): def authenticate(self, request, username=None, password=None, **kwargs): UserModel = get_user_model() if username is None: username = kwargs.get(UserModel.USERNAME_FIELD) if username is None: return None try: case_insensitive_username_field = '{}__iexact'.format(UserModel.USERNAME_FIELD) user = UserModel._default_manager.get(**{case_insensitive_username_field: username}) except UserModel.DoesNotExist: return None if user.check_password(password) and self.user_can_authenticate(user): return user
3. 仅小写密码可登录的问题排查
该问题和你提供的当前代码没有直接关联,请按以下方向检查:
- 检查自定义注册表单
MyUserCreationForm的clean/clean_password方法,是否存在将用户输入的密码转为小写后再存储的逻辑,注册时如果转了小写,登录时自然只有输入小写密码才能匹配哈希值。 - 检查登录页前端代码,是否有JS脚本自动将密码输入框的内容转为小写后再提交。
- 确认你自定义的用户模型中,没有重写
set_password方法对输入密码做小写转换处理。
内容的提问来源于stack exchange,提问作者Saud Zubedi
相关产品推荐
相关产品推荐

