You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django自定义用户模型调用authenticate()认证返回None问题

问题原因

authenticate()返回None是两个核心错误共同导致的:

  • 密码存储错误:你数据库里的用户密码是明文存储的,没有做Django要求的加盐哈希处理。正常Django用户表的password字段存的是类似pbkdf2_sha256$320000$随机盐$哈希值格式的字符串,从你的运行日志看,数据库取出的password和用户输入的明文完全一致,说明你创建用户时直接给password字段赋值了明文,没有走密码哈希逻辑。Django默认认证后端会把传入的明文密码做哈希后,和数据库存储的哈希值比对,存明文的情况下比对必然失败。
  • 排查代码传参错误:你排查问题时,把从数据库取出的x.password作为密码参数传给authenticate()。这个方法的password参数必须传用户输入的原始明文密码,内部会自动完成哈希校验,你传数据库存储的密码值,相当于把存储值当明文再做一次哈希去和库中值比对,永远不可能匹配。

另外你代码里导入的from django.contrib.auth.models import User是冗余代码,自定义用户模型继承AbstractUser后不需要再导入原生User模型,这个问题不会影响认证逻辑。

修复方法
  • 修正用户创建逻辑:所有用户创建场景必须调用set_password()方法处理明文密码,禁止直接给password字段赋明文字符串。代码创建用户参考如下写法,创建管理员账号直接用python manage.py createsuperuser命令即可,该命令会自动做密码哈希:
from users.models import UserDetails

# 正确创建普通用户
user = UserDetails.objects.create(
    username='moradi',
    # 其余自定义字段按实际需求赋值
)
user.set_password('r123456m123456') # 传入明文,内部自动完成哈希加盐
user.save()
  • 修正登录视图传参:authenticate()必须传入表单接收的用户明文账号密码,不要传数据库查询出的password字段,同时建议传入request参数适配Django新版认证逻辑,修正后的登录视图代码:
def LoginPage(request):
    forms = LoginForm()
    if request.method == 'POST':
        forms = LoginForm(request.POST)
        if forms.is_valid():
            username = forms.cleaned_data['Username']
            password = forms.cleaned_data['Password']
            # 传入request和用户输入的明文凭证做认证
            user = authenticate(request, username=username, password=password)
            if user:
                login(request, user)
                return redirect('/stock')
    context = {'form': forms}
    return render(request, "users/login.html", context)
  • 修复存量脏数据:之前明文存储密码的用户数据全部无法通过认证,可以直接删除后重新按正确方式创建,也可以逐一对存量用户调用set_password()重新设置密码生成正确哈希值。

内容的提问来源于stack exchange,提问作者soroush khani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 17:27:33