使用Django DRF Simple-JWT自定义用户认证遇账户错误求助
解决Django REST Framework Simple JWT登录报错"No active account found with the given credentials"
我看了你用自定义用户结合simplejwt做认证的代码,这个报错大概率是自定义UserManager里的逻辑问题,还有认证字段匹配的小细节没处理好,下面一步步给你排查修复:
1. 先修复超级用户创建的bug
你的create_superuser方法有两个明显的逻辑错误:
- 调用
create_user后没有接收返回的用户对象,导致后续修改的user是未定义的无效变量 user.is_staff()是调用方法,不是设置属性,应该直接赋值布尔值
修改后的create_superuser代码:
def create_superuser(self, email, username, password): # 接收create_user返回的用户对象 user = self.create_user(email, username, password) # 直接给属性赋值,不是调用方法 user.is_staff = True user.is_superuser = True user.save() return user
2. 确保认证时用对字段
你把USERNAME_FIELD设为了email,但simplejwt默认会用username字段去匹配登录凭证,这就会导致匹配失败。有两种解决方式:
方式一:在settings里配置JWT字段
直接在settings.py中添加Simple JWT的配置,指定用email作为认证的用户标识字段:
from datetime import timedelta SIMPLE_JWT = { 'ACCESS_TOKEN_LIFETIME': timedelta(minutes=5), 'REFRESH_TOKEN_LIFETIME': timedelta(days=1), # 指定认证时关联的用户字段为email 'USER_ID_FIELD': 'email', }
方式二:自定义Token获取视图
如果需要更灵活的控制(比如给token添加自定义字段),可以自定义视图和序列化器:
# 在你的views.py中 from rest_framework_simplejwt.views import TokenObtainPairView from rest_framework_simplejwt.serializers import TokenObtainPairSerializer class CustomTokenObtainPairSerializer(TokenObtainPairSerializer): @classmethod def get_token(cls, user): token = super().get_token(user) # 可选:给token添加自定义字段,比如用户名 token['username'] = user.username return token def validate(self, attrs): # 把前端传的email值赋值给username字段,适配simplejwt的默认验证逻辑 attrs['username'] = attrs.get('email') return super().validate(attrs) class CustomTokenObtainPairView(TokenObtainPairView): serializer_class = CustomTokenObtainPairSerializer
然后修改urls.py中的路由:
urlpatterns = [ url(r'^api/token/$', CustomTokenObtainPairView.as_view(), name='token_obtain_pair'), url(r'^api/token/refresh/$', TokenRefreshView.as_view(), name='token_refresh'), ]
3. 验证用户数据的正确性
- 确保创建用户时用的是
User.objects.create_user或create_superuser方法,不要直接用User.objects.create——因为直接create不会对密码进行加密,导致登录时密码匹配失败 - 可以在Django Shell里验证密码是否正确加密:
from django.contrib.auth import get_user_model User = get_user_model() user = User.objects.get(email='你的测试邮箱') print(user.check_password('你的测试密码')) # 正常应该返回True,返回False说明密码未正确加密
4. 确认用户激活状态
虽然你说用户都是激活状态,还是可以在Shell里再确认一下:
print(user.is_active) # 应该返回True
按照上面的步骤修改后,应该就能解决登录时报错的问题了。
内容的提问来源于stack exchange,提问作者A.JRJ
相关产品推荐
相关产品推荐

