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

Django登出POST请求返回403错误,CSRF相关问题排查

解决方案

一、类视图的CSRF配置(正确用法)

1. 启用CSRF保护(优先方案)

类视图的CSRF装饰器要作用在dispatch方法上(这是所有请求的入口),用method_decorator实现:

from django.views.decorators.csrf import csrf_protect
from django.utils.decorators import method_decorator
from django.views import View

@method_decorator(csrf_protect, name='dispatch')
class LogoutView(View):
    def post(self, request):
        request.session.flush()
        return JsonResponse({'status': 'success'})

如果是DRF的APIView,需确保认证类包含SessionAuthentication(DRF对session认证的视图会自动启用CSRF验证):

from rest_framework.views import APIView
from rest_framework.authentication import SessionAuthentication

class LogoutView(APIView):
    authentication_classes = [SessionAuthentication]
    
    def post(self, request):
        request.session.flush()
        return Response({'status': 'success'})

2. 豁免CSRF(仅应急,不推荐)

如果必须豁免,同样装饰dispatch方法:

from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator

@method_decorator(csrf_exempt, name='dispatch')
class LogoutView(View):
    def post(self, request):
        # 登出逻辑

二、前端正确传递CSRF Token(核心问题)

后端返回403,大概率是前端没按Django要求传递Token。Django接受三种方式,AJAX请求优先认X-CSRFToken请求头:

  1. 获取CSRF Token:从Cookie中读取csrftoken(可使用js-cookie库简化操作)
  2. 发送请求时带上Token:必须添加credentials: 'include'确保Cookie被传递

Axios示例:

import Cookies from 'js-cookie';
import axios from 'axios';

// 全局配置自动携带CSRF头
axios.defaults.xsrfCookieName = 'csrftoken';
axios.defaults.xsrfHeaderName = 'X-CSRFToken';
axios.defaults.withCredentials = true; // 等价于credentials: include

// 登出请求
const handleLogout = async () => {
  try {
    await axios.post('/api/logout/');
    // 处理登出后逻辑
  } catch (err) {
    console.error(err);
  }
};

原生Fetch示例:

const csrftoken = Cookies.get('csrftoken');
fetch('/api/logout/', {
  method: 'POST',
  headers: {
    'X-CSRFToken': csrftoken,
    'Content-Type': 'application/json',
  },
  credentials: 'include', // 必须加,否则浏览器不发送Cookie
});

三、LoginView未触发CSRF验证的原因及修复

之前LoginView没验证CSRF,大概率是:

  • 视图继承DRF的APIView但未配置SessionAuthentication,DRF默认对非session认证视图豁免CSRF
  • 视图被隐式添加了csrf_exempt装饰器

修复方式:给LoginView也加上csrf_protect装饰器(同第一部分的类视图装饰方式),同时确保前端正确传递Token,即可触发正常验证。

四、为什么GET请求登出能工作?

Django对GET请求默认跳过CSRF验证,但登出用GET存在安全风险(恶意网站可通过诱导点击触发登出),所以强烈建议用POST+CSRF验证的方案。


内容的提问来源于stack exchange,提问作者Hamzah Al-Hamadani

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 21:04:57