Django Rest Framework Token认证失效:登录提示无效凭证
解决Django REST框架登录返回"Invalid credentials"问题
问题根源
- 注册时密码未加密:
UserSerializer作为ModelSerializer,默认会将密码以明文形式存入数据库,但Django认证系统仅识别加密后的密码,导致登录时密码验证失败。 - 登录序列化器无验证逻辑:
UserLoginSerializer仅定义了字段结构,未实现用户名与密码的匹配验证,因此serializer.validated_data中不存在user对象,视图无法获取合法用户。
具体修复步骤
1. 修复注册序列化器(serializers.py)
重写create方法确保密码加密存储,同时为登录序列化器添加验证逻辑:
from rest_framework import serializers from django.contrib.auth.models import User class UserSerializer(serializers.ModelSerializer): class Meta: model = User fields = ('id', 'username', 'email', 'password', 'first_name', 'last_name') extra_kwargs = {'password': {'write_only': True}} def create(self, validated_data): # 提取密码并从验证数据中移除 password = validated_data.pop('password') # 创建用户实例 user = User(**validated_data) # 加密密码后保存 user.set_password(password) user.save() return user class UserLoginSerializer(serializers.Serializer): username = serializers.CharField() password = serializers.CharField(write_only=True) def validate(self, attrs): username = attrs.get('username') password = attrs.get('password') if username and password: # 查询对应用户 user = User.objects.filter(username=username).first() # 验证密码合法性 if user and user.check_password(password): attrs['user'] = user return attrs raise serializers.ValidationError("用户名或密码错误") raise serializers.ValidationError("必须提供用户名和密码")
2. 简化登录视图逻辑(views.py)
借助序列化器的验证结果,精简视图中的判断逻辑:
from django.shortcuts import render from rest_framework import generics, permissions, status from rest_framework.response import Response from django.contrib.auth import login, logout from django.contrib.auth.models import User from rest_framework.permissions import AllowAny from .serializers import UserSerializer, UserLoginSerializer from rest_framework.authtoken.models import Token class UserRegisterView(generics.CreateAPIView): queryset = User.objects.all() serializer_class = UserSerializer permission_classes = [permissions.AllowAny] class UserLoginView(generics.CreateAPIView): serializer_class = UserLoginSerializer permission_classes = [permissions.AllowAny] def post(self, request, *args, **kwargs): serializer = self.serializer_class(data=request.data, context={'request': request}) if serializer.is_valid(): user = serializer.validated_data['user'] login(request, user) token, created = Token.objects.get_or_create(user=user) return Response({'token': token.key, 'message': 'Login successful'}, status=status.HTTP_200_OK) # 返回序列化器的具体错误信息,便于调试 return Response(serializer.errors, status=status.HTTP_401_UNAUTHORIZED) class UserLogoutView(generics.GenericAPIView): permission_classes = [permissions.IsAuthenticated] def post(self, request, *args, **kwargs): logout(request) return Response({'message': 'Logout successful'}, status=status.HTTP_200_OK)
3. 重置测试用户
此前注册的用户密码为明文,需在admin后台删除这些用户,或直接在admin中为其设置新密码(admin会自动加密),之后重新注册测试账号。
验证修复
- 用Postman重新注册用户,此时密码会被加密存储;
- 使用相同用户名和密码登录,应返回成功的token及提示消息。
内容的提问来源于stack exchange,提问作者Abhishek Misra
相关产品推荐
相关产品推荐

