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

Django自定义用户knox认证失败,authenticate返回None求助

问题根源与解决方案

核心问题:用户密码未正确加密

从你在Django Shell的测试结果可以明确:你能通过get_user_model().objects.get找到用户,但authenticate返回None,这说明用户密码是明文存储的,而Django的authenticate方法会使用加密后的密码进行校验,自然匹配失败,最终导致serializer.is_valid()返回False。

问题出在post_save信号的用户创建逻辑里:

get_user_model().objects.create(company=instance, username=instance.name, password=instance.password)

直接用create方法设置password字段会把明文密码存入数据库,而Django要求用户密码必须通过set_password()方法加密后存储。

修复步骤

1. 修正用户创建的信号逻辑

修改models.py中的信号接收器代码,改用set_password处理密码:

@receiver(post_save, sender=Company)
def list_create(sender, instance=None, created=False, **kwargs):
    if created:
        # 先创建用户对象,不设置密码
        user = get_user_model().objects.create(company=instance, username=instance.name)
        # 使用set_password加密密码后保存
        user.set_password(instance.password)  # 注意:需确保Company模型包含password字段
        user.save()

补充:你的Company模型代码里没有定义password字段,需要先添加该字段,否则instance.password会报错:

class Company(m.Model):
    # ... 现有字段
    password = m.CharField(max_length=128)  # 添加密码字段

2. 更新现有用户的密码

对于已经创建的测试用户(比如CIEMSA),需要在Django Shell中手动更新密码:

>>> from django.contrib.auth import get_user_model
>>> user = get_user_model().objects.get(username="CIEMSA")
>>> user.set_password("225236Cm.")
>>> user.save()

之后再测试authenticate,应该能正常返回用户对象:

>>> print(authenticate(username="CIEMSA", password="225236Cm."))
<MyUser: CIEMSA>

3. 验证视图逻辑

你的LoginAPI视图代码本身没有问题,修复密码加密后,serializer.is_valid()应该能正常通过,登录流程即可正常工作。

额外注意事项

  • 永远不要直接明文存储用户密码,必须使用Django提供的set_password()或create_user()方法(create_user会自动处理密码加密)。
  • 若使用create_user,信号逻辑也可以简化为:
    get_user_model().objects.create_user(company=instance, username=instance.name, password=instance.password)
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 09:57:41