Django自定义手机号登录:超级用户可登普通用户登失败问题
可能原因1:普通用户密码未正确哈希存储
超级用户通过createsuperuser命令创建时,会自动调用CustomUserManager.create_superuser,进而触发set_password()对密码进行哈希处理。但如果普通用户是通过直接创建模型实例(比如CustomUser.objects.create(phone_number='13xxxx', password='123456'))而非调用create_user方法创建的,密码会以明文存储,导致authenticate验证时哈希匹配失败。
解决方法:
确保创建普通用户时必须调用CustomUserManager的create_user方法:
# 示例:在shell或注册视图中创建用户 from detectapp.models import CustomUser CustomUser.objects.create_user(phone_number='13xxxxxxxxx', password='your_password')
可能原因2:authenticate参数不匹配默认认证后端预期
Django默认的ModelBackend在处理自定义用户模型时,虽会使用USERNAME_FIELD指定的字段,但部分场景下需要显式传递username参数而非自定义字段名(即phone_number)。当前代码中直接传递phone_number=phone_number可能导致后端无法正确识别用户名字段。
解决方法:
修改views.py中的authenticate调用,将phone_number参数替换为username:
# 原代码 user = authenticate(request, phone_number=phone_number, password=password) # 修改后 user = authenticate(request, username=phone_number, password=password)
可能原因3:普通用户的is_active字段被意外设置为False
虽然模型中is_active默认值为True,但如果注册或修改用户时手动将其设为False,会导致用户无法登录(代码中已判断user.is_active,但如果authenticate直接返回None,可能不会走到这个分支)。
排查方法:
在Django shell中检查普通用户的is_active状态:
user = CustomUser.objects.get(phone_number='你的普通用户手机号') print(user.is_active) # 应为True
如果为False,执行user.is_active = True; user.save()修复。
可能原因4:手机号存在格式不匹配(如空格、特殊字符)
注册时如果手机号包含空格或其他特殊字符,而登录时输入的是纯数字,会导致数据库中存储的手机号与登录输入不匹配,进而authenticate无法找到用户。
排查方法:
检查数据库中普通用户的phone_number字段值,确保与登录输入完全一致:
user = CustomUser.objects.get(phone_number='你的普通用户手机号') print(user.phone_number) # 与登录输入对比是否一致
内容的提问来源于stack exchange,提问作者Shriyansh

