Django自定义用户登录API报“无效邮箱或密码”错误求助
问题分析与解决方法
核心错误原因
- 自定义User模型冗余字段导致密码未哈希存储:继承
AbstractBaseUser的模型无需手动添加password字段,该基类已内置密码哈希存储逻辑。手动添加的password = models.CharField(max_length=100)会让注册时明文密码直接存入数据库,而check_password()方法仅验证哈希值,自然匹配失败。 - 用户注册时未正确调用密码哈希方法:
UserRegistrationSerializer的create方法直接用User.objects.create()创建用户,未调用set_password()哈希密码,导致数据库存储明文密码。 - 视图中存在模型导入冲突:
views.py同时导入自定义User和Django自带User模型,造成代码引用混乱。
修复步骤
1. 修正models.py中的User模型
移除手动添加的password字段,保留基类内置的密码逻辑:
from django.db import models from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin class Address(models.Model): TYPE_CHOICES = [ ('office', 'Office'), ('factory', 'Factory') ] type = models.CharField(max_length=10, choices=TYPE_CHOICES) addressLine1 = models.CharField(max_length=100) addressLine2 = models.CharField(max_length=100, blank=True, null=True) addressLine3 = models.CharField(max_length=100, blank=True, null=True) postal_code = models.CharField(max_length=20) state = models.CharField(max_length=100) city = models.CharField(max_length=100) country = models.CharField(max_length=100) class UserManager(BaseUserManager): def create_user(self, email, username, password=None): if not email: raise ValueError('The Email field must be set') email = self.normalize_email(email) user = self.model(email=email, username=username) user.set_password(password) user.save(using=self._db) return user def create_superuser(self, email, username, password): user = self.create_user(email, username, password) user.is_staff = True user.is_superuser = True user.save(using=self._db) return user class User(AbstractBaseUser): username = models.CharField(max_length=100, unique=True) email = models.EmailField(unique=True) # 移除手动添加的password字段 phone = models.CharField(max_length=20) address = models.OneToOneField(Address, on_delete=models.CASCADE) business_category = models.CharField(max_length=100) number_of_employees = models.CharField(max_length=50) usage_description = models.TextField(blank=True) otp = models.CharField(max_length=6, null=True, blank=True) is_active = models.BooleanField(default=False) is_verified = models.BooleanField(default=False) objects = UserManager() USERNAME_FIELD = 'email' REQUIRED_FIELDS = ['username']
2. 修正serializers.py中的UserRegistrationSerializer
创建用户时调用set_password()哈希密码,并设置密码为仅写入字段:
from rest_framework import serializers from .models import User, Address # 其他序列化器保持不变 class UserRegistrationSerializer(serializers.ModelSerializer): address = AddressSerializer() class Meta: model = User fields = '__all__' extra_kwargs = {'password': {'write_only': True}} def create(self, validated_data): address_data = validated_data.pop('address') address = Address.objects.create(**address_data) user = User.objects.create(address=address, **validated_data) user.set_password(validated_data['password']) user.save() return user
3. 修正views.py中的模型导入冲突
删除Django自带User模型的导入,仅保留自定义模型:
# 移除该行:from django.contrib.auth.models import User from .models import User # 其他导入保持不变
4. 重新迁移数据库
修改模型后需更新数据库结构:
python manage.py makemigrations python manage.py migrate
5. 重新注册测试用户
删除之前注册的旧用户(密码为明文存储),重新注册新用户确保密码以哈希形式存储。
验证修复效果
重新发起登录请求,user.check_password(password)会正确验证哈希密码,登录成功后将返回Token及成功提示。
内容的提问来源于stack exchange,提问作者Subhajit Das
相关产品推荐
相关产品推荐

