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

Django+React登录功能遇401 Unauthorized及405 Method Not Allowed错误求助

Django+React登录功能遇401 Unauthorized及405 Method Not Allowed错误求助

先解决直观的405 Method Not Allowed错误

你访问GET /api/farmer/login/时出现这个错误,原因其实很明确:你的Django视图FarmerLoginView只定义了post方法,接口返回的Allow: POST, OPTIONS也直接说明了——这个登录接口只接受POST请求,不支持GET请求。

浏览器地址栏访问默认是GET方法,所以直接输地址肯定会报错。正常的登录流程应该是通过React表单提交POST请求,这部分你代码里的POST逻辑是对的,只要别用GET访问这个接口就没问题。

重点排查401 Unauthorized错误(登录失败核心问题)

这个错误是因为你的登录认证逻辑存在几个关键漏洞,导致服务器认为凭证无效,返回401:

1. 密码未正确哈希存储

你的Farmer和Customer模型里的set_password方法只是直接把明文密码赋值给字段:

def set_password(self, password):
    self.password = password

但Django的authenticate函数默认只认哈希后的密码,如果注册时你直接把明文密码存进数据库,authenticate会匹配失败,返回None,进而触发401错误。

修复方法:修改模型的set_password方法,用Django内置的make_password工具哈希密码:

from django.contrib.auth.hashers import make_password

def set_password(self, password):
    self.password = make_password(password)

同时要确保你在创建用户(注册)时,是调用set_password方法设置密码,而不是直接给password字段赋值。

2. 缺少自定义用户认证后端

你的视图里用authenticate(request=request, email=farmer.email, password=password)来验证,但Django默认的认证后端是基于username字段的,而你的Farmer和Customer模型并没有username字段,只有email和phone_number。

默认的authenticate函数根本识别不了email这个参数,会直接返回None。你需要自定义一个认证后端,支持通过邮箱或手机号登录:

先在你的app下创建backends.py文件:

from django.contrib.auth.backends import BaseBackend
from .models import Farmer, Customer

class FarmerAuthBackend(BaseBackend):
    def authenticate(self, request, email_or_mobile=None, password=None, **kwargs):
        # 先尝试通过邮箱找Farmer
        try:
            farmer = Farmer.objects.get(email=email_or_mobile)
        except Farmer.DoesNotExist:
            # 再尝试通过手机号找
            try:
                farmer = Farmer.objects.get(phone_number=email_or_mobile)
            except Farmer.DoesNotExist:
                return None
        # 验证密码(用check_password自动匹配哈希值)
        if farmer.check_password(password):
            return farmer

    def get_user(self, user_id):
        try:
            return Farmer.objects.get(pk=user_id)
        except Farmer.DoesNotExist:
            return None

# 同理创建Customer的认证后端
class CustomerAuthBackend(BaseBackend):
    def authenticate(self, request, email_or_mobile=None, password=None, **kwargs):
        try:
            customer = Customer.objects.get(email=email_or_mobile)
        except Customer.DoesNotExist:
            try:
                customer = Customer.objects.get(phone_number=email_or_mobile)
            except Customer.DoesNotExist:
                return None
        if customer.check_password(password):
            return customer

    def get_user(self, user_id):
        try:
            return Customer.objects.get(pk=user_id)
        except Customer.DoesNotExist:
            return None

然后在settings.py里配置认证后端:

AUTHENTICATION_BACKENDS = [
    'yourapp.backends.FarmerAuthBackend',
    'yourapp.backends.CustomerAuthBackend',
    # 保留默认后端可选,根据你的需求调整
    'django.contrib.auth.backends.ModelBackend',
]

之后修改视图里的authenticate调用,改为传入email_or_mobile参数,而不是email:

# FarmerLoginView里的代码
farmer_user = authenticate(request=request, email_or_mobile=email_or_mobile, password=password)

这样就能正确触发自定义后端的认证逻辑了。

3. React表单存在重复提交问题

你的React表单里,form标签绑定了onSubmit={handleSubmit},同时两个按钮又绑定了onClick={(event) => handleSubmit(event, 'farmer')},这会导致点击按钮时,表单的onSubmit和按钮的onClick会同时触发,可能导致重复请求或者数据异常。

修复方法:移除form的onSubmit绑定,只保留按钮的onClick:

<form>

这样就不会重复触发请求了。

4. 序列化器未被利用(可选优化)

你写了UserLoginSerializer但在视图里并没有用上,而是手动处理request.data,可以考虑用序列化器来统一验证数据,减少重复代码:

修改FarmerLoginView的post方法:

def post(self, request):
    serializer = UserLoginSerializer(data=request.data, context={'request': request})
    if serializer.is_valid():
        user = serializer.validated_data['user']
        login(request, user)
        return Response({'message': 'Login successful'}, status=status.HTTP_200_OK)
    return Response({'message': 'Invalid login credentials'}, status=status.HTTP_401_UNAUTHORIZED)

这样能让代码更简洁,也能统一验证逻辑。

总结修复步骤

  1. 确保用户密码在注册时是哈希存储的,修改模型的set_password方法。
  2. 自定义认证后端,支持邮箱/手机号登录,并在settings中配置。
  3. 修正视图中authenticate的参数,使用自定义后端的验证字段。
  4. 修复React表单的重复提交问题。

按照这些步骤调整后,应该就能解决401错误,同时405错误只要不使用GET访问登录接口就不会出现了。

备注:内容来源于stack exchange,提问作者TechLover

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.22 09:38:10