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

Django REST Framework登录接口认证失败问题求助

Django REST Framework 登录认证失败问题排查与修复

核心问题分析

你的登录接口认证失败主要由以下3个问题导致:

1. 错误从serializer.data获取密码

serializer.data是序列化后的输出数据,如果密码字段设置为write_only=True,该字段不会出现在data中。登录时应该从serializer.validated_data(验证通过的输入数据)中提取邮箱和密码。

2. 登录序列化器未正确配置密码字段

UserLoginSerializer继承自ModelSerializer,但未显式将password设为write_only=True,且没有覆盖为明文输入的CharField(模型中password是哈希存储,登录需要接收明文密码)。

3. 用户模型可能未配置邮箱作为登录凭证

如果自定义User模型未设置USERNAME_FIELD = 'email',authenticate(email=xxx, password=xxx)会失效——Django默认使用username字段做认证匹配。


修复代码

1. 修复serializers.py中的UserLoginSerializer

推荐改用Serializer而非ModelSerializer(登录不需要序列化用户模型返回),并添加基础验证逻辑:

from rest_framework import serializers
from authentication.models import User

class UserRegistrationSerializer(serializers.ModelSerializer):
    password2 = serializers.CharField(style={"input_type": "password"}, write_only=True)

    class Meta:
        model = User
        fields = ["email", "username", "password", "password2"]
        extra_kwargs = {"password": {"write_only": True}}

    def validate(self, attrs):
        password = attrs.get("password")
        password2 = attrs.get("password2")
        if password != password2:
            raise serializers.ValidationError(
                "密码与确认密码不匹配"
            )
        return attrs

    def create(self, validated_data):
        # 移除多余的password2字段再创建用户
        validated_data.pop('password2')
        return User.objects.create_user(**validated_data)

# 修复后的登录序列化器
class UserLoginSerializer(serializers.Serializer):
    email = serializers.EmailField(max_length=100)
    password = serializers.CharField(style={"input_type": "password"}, write_only=True)

    def validate(self, attrs):
        email = attrs.get('email')
        # 提前验证邮箱是否已注册
        if not User.objects.filter(email=email).exists():
            raise serializers.ValidationError("该邮箱未注册")
        return attrs

2. 修复views.py中的UserLoginView

改用validated_data获取参数,并修正认证逻辑和状态码(401表示未授权,比404更符合语义):

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from django.contrib.auth import authenticate
from authentication.serializers import UserLoginSerializer, UserRegistrationSerializer

class UserRegistrationView(APIView):
    def post(self, request, format=None):
        serializer = UserRegistrationSerializer(data=request.data)
        if serializer.is_valid(raise_exception=True):
            user = serializer.save()
            return Response(
                {"msg": "注册成功"}, status=status.HTTP_201_CREATED
            )
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

class UserLoginView(APIView):
    def post(self, request, format=None):
        serializer = UserLoginSerializer(data=request.data)
        if serializer.is_valid(raise_exception=True):
            # 从validated_data获取验证后的输入值
            email = serializer.validated_data.get('email')
            password = serializer.validated_data.get('password')
            
            # 若User模型设置了USERNAME_FIELD = 'email',直接用email参数;否则改用username=email
            user = authenticate(request=request, email=email, password=password)

            if user is not None:
                return Response({"msg": "登录成功"}, status=status.HTTP_200_OK)
            else:
                return Response(
                    {
                        "errors": {
                            "non_field_errors": ["邮箱或密码不正确"]
                        }
                    },
                    status=status.HTTP_401_UNAUTHORIZED
                )
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

3. 确认自定义User模型配置(关键)

确保models.py中的User模型设置了邮箱作为登录凭证,并在settings.py中指定自定义用户模型:

# authentication/models.py
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
from django.db import models

class UserManager(BaseUserManager):
    def create_user(self, email, username, password=None, **extra_fields):
        if not email:
            raise ValueError('用户必须提供邮箱')
        email = self.normalize_email(email)
        user = self.model(email=email, username=username, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

class User(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(unique=True)
    username = models.CharField(max_length=100)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)

    USERNAME_FIELD = 'email'  # 核心:设置邮箱为登录验证字段
    REQUIRED_FIELDS = ['username']

    objects = UserManager()

在项目根目录的settings.py中添加:

AUTH_USER_MODEL = 'authentication.User'

内容的提问来源于stack exchange,提问作者muyiwa. py

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 19:35:21