Django Rest Framework登录报错:Postman无法登录,提示invalid credentials
问题:注册正常但登录提示
invalid credentials 我正在开发一款支持通过Postman注册、登录的Web应用,目前注册功能正常,但登录时提示invalid credentials,无法成功登录。以下是项目中的代码:
serializer.py
from rest_framework import serializers from django.contrib.auth.models import User from rest_framework_simplejwt.tokens import RefreshToken from django.contrib.auth import authenticate class RegisterSerializer(serializers.Serializer): first_name = serializers.CharField() last_name = serializers.CharField() username = serializers.CharField() password = serializers.CharField() def validate(self, data): if User.objects.filter(username=data["username"]).exists(): raise serializers.ValidationError("username is already taken") return data def create(self, validated_data): user = User.objects.create(first_name=validated_data["first_name"], last_name=validated_data["last_name"], username=validated_data["username"].lower() ) user.set_password(validated_data["password"]) return validated_data class LoginSerializer(serializers.Serializer): username = serializers.CharField() password = serializers.CharField() def validate(self, data): if not User.objects.filter(username=data["username"]).exists(): raise serializers.ValidationError("account not found") return data def get_jwt_token(self, data): user = authenticate(username=data["username"], password=data["password"]) if not user: return {"message": "invalid credentials", "data": {}} refresh = RefreshToken.for_user(user) return { "message": "login success", "data": {"token": {"refresh": str(refresh), "access": str(refresh.access_token)}}}
views.py
from rest_framework.views import APIView from rest_framework.response import Response from .serializer import RegisterSerializer, LoginSerializer from rest_framework import status class RegisterView(APIView): def post(self, request): try: data = request.data serializer = RegisterSerializer(data=data) if not serializer.is_valid(): return Response ({ "data" : serializer.errors, "message" : "something went wrong", }, status=status.HTTP_400_BAD_REQUEST) serializer.save() return Response({ "data" : {}, "message" : "user created successfully", }, status=status.HTTP_201_CREATED) except Exception as e: print(e) return Response({ "data" : {}, "message" : "something went wrong", }, status=status.HTTP_400_BAD_REQUEST) class LoginView(APIView): def post(self,request): try: data = request.data serializer = LoginSerializer(data=data) if not serializer.is_valid(): return Response({ "data": serializer.errors, "message": "something went wrong", }, status=status.HTTP_400_BAD_REQUEST) response = serializer.get_jwt_token(serializer.data) return Response(response, status=status.HTTP_200_OK) except Exception as e: print(e) return Response({ "data" : {}, "message" : "something went wrong", }, status=status.HTTP_400_BAD_REQUEST)
我已查阅JWT相关文档,仍未找到问题根源,希望能得到故障排查的帮助。
故障排查及修复方案
核心问题1:注册时未保存密码修改
在RegisterSerializer的create方法中,你通过User.objects.create()创建了用户并写入数据库,但之后调用user.set_password()修改了密码哈希,却没有执行user.save()将更新后的密码同步到数据库。这会导致数据库中存储的用户密码是无效的空白状态,最终authenticate验证失败,返回invalid credentials。
核心问题2(可选优化):用户名大小写不匹配
注册时你将用户名转为小写存储,但登录时直接使用用户输入的原始用户名进行验证。如果用户登录时输入大写字母,会出现“账号存在但验证失败”的矛盾情况(validate阶段能查到用户,但authenticate因为用户名大小写不匹配失败)。
修复代码
1. 修复RegisterSerializer的create方法
添加user.save()保存密码修改,同时建议返回用户对象(符合Serializer规范):
def create(self, validated_data): user = User.objects.create( first_name=validated_data["first_name"], last_name=validated_data["last_name"], username=validated_data["username"].lower() ) user.set_password(validated_data["password"]) user.save() # 新增:保存更新后的密码到数据库 return user # 推荐返回user对象,而非validated_data
2. 修复LoginSerializer的用户名大小写问题
在get_jwt_token方法中将用户名转为小写,和注册逻辑保持一致:
def get_jwt_token(self, data): # 转为小写,匹配注册时的存储规则 username = data["username"].lower() user = authenticate(username=username, password=data["password"]) if not user: return {"message": "invalid credentials", "data": {}} refresh = RefreshToken.for_user(user) return { "message": "login success", "data": { "token": { "refresh": str(refresh), "access": str(refresh.access_token) } } }
验证步骤
- 重新注册一个新用户
- 使用该用户的用户名(大小写均可,若完成第二步修复)和密码登录,即可正常获取JWT Token。
内容的提问来源于stack exchange,提问作者Balage
相关产品推荐
相关产品推荐

