simple-jwt登录验证失败:无有效账户错误排查求助
解决Simple-JWT自定义User模型登录报错问题
问题现象
自定义User模型支持邮箱/手机号登录,但集成simple-jwt时持续返回:
{
"detail": "No active account found with the given credentials"
}
已确认账户为激活状态,尝试过新创建的超级用户,问题仍存在。
代码问题分析与修复
1. models.py 错误修复
- 重复定义password字段:AbstractBaseUser已内置password字段,自定义User中重复定义会导致
set_password()无法正确加密存储密码,需删除该字段。 - 无用代码冗余:
create_user方法中user = self.normalize_email(email)属于无效赋值,需删除并在model初始化时正确处理邮箱格式化。
修改后的models.py核心代码:
class CustomUserManager(BaseUserManager): def create_user(self, name, email, phone_number, password, **other_fields): if not phone_number: raise ValueError('You must provide a phone number') # 正确格式化邮箱并初始化用户 user = self.model(email=self.normalize_email(email), name=name, phone_number=phone_number, **other_fields) user.set_password(password) user.save() return user # 超级用户创建方法保持不变... class User(AbstractBaseUser, PermissionsMixin): name = models.CharField(max_length=200) email = models.EmailField(unique=True, null=True) phone_number = models.CharField(max_length=50, unique=True) # 移除重复定义的password字段 is_staff = models.BooleanField(default=False) is_active = models.BooleanField(default=False) objects = CustomUserManager() USERNAME_FIELD = 'phone_number' REQUIRED_FIELDS =['name', 'email'] def __str__(self): return self.name
2. backends.py 认证逻辑修复
- 缺少用户活跃状态检查:authenticate方法未验证
user.is_active,与simple-jwt默认认证规则冲突,需添加该检查。 - 冗余try-except嵌套:用Q对象合并邮箱/手机号查询逻辑,简化代码结构。
修改后的backends.py代码:
from django.contrib.auth.backends import ModelBackend from django.contrib.auth import get_user_model from django.db.models import Q class EmailOrPhoneNumberBackend(ModelBackend): def authenticate(self, request, username=None, password=None, **kwargs): UserModel = get_user_model() try: # 用Q对象同时匹配邮箱或手机号 user = UserModel.objects.get(Q(email=username) | Q(phone_number=username)) except UserModel.DoesNotExist: return None # 同时验证密码正确性与用户活跃状态 if user.check_password(password) and user.is_active: return user def get_user(self, user_id): UserModel = get_user_model() try: return UserModel.objects.get(pk=user_id) except UserModel.DoesNotExist: return None
3. settings.py 配置优化
SIMPLE_JWT中USER_ID_FIELD建议使用主键id(默认值),而非phone_number,避免字符串作为用户ID带来的潜在问题:
SIMPLE_JWT = { 'AUTH_HEADER_TYPES': ('Bearer',), 'AUTH_HEADER_NAME': 'HTTP_AUTHORIZATION', 'USER_ID_FIELD': 'id', # 改为主键字段 'USER_ID_CLAIM': 'user_id', 'USER_AUTHENTICATION_RULE': 'rest_framework_simplejwt.authentication.default_user_authentication_rule', }
后续操作
- 执行数据库迁移:
python manage.py makemigrations && python manage.py migrate - 重新创建测试用户/超级用户:
python manage.py createsuperuser(确保新用户密码被正确加密) - 再次调用simple-jwt的登录接口,使用邮箱或手机号作为
username参数,即可正常获取Token。
内容的提问来源于stack exchange,提问作者Yoocee Ansah
相关产品推荐
相关产品推荐

