You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django Rest Framework Token认证失效:登录提示无效凭证

解决Django REST框架登录返回"Invalid credentials"问题

问题根源

  1. 注册时密码未加密:UserSerializer作为ModelSerializer,默认会将密码以明文形式存入数据库,但Django认证系统仅识别加密后的密码,导致登录时密码验证失败。
  2. 登录序列化器无验证逻辑: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会自动加密),之后重新注册测试账号。

验证修复

  1. 用Postman重新注册用户,此时密码会被加密存储;
  2. 使用相同用户名和密码登录,应返回成功的token及提示消息。

内容的提问来源于stack exchange,提问作者Abhishek Misra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 16:57:32