基于Django+React+Axios的POST请求:如何获取csrftoken Cookie?
解决Django DRF + React跨域下获取CSRF Token并POST表单的问题
你遇到的Cookie获取不到的核心原因是跨域请求下浏览器的同源策略限制,再加上代码里的几处逻辑问题,我们一步步来解决:
一、先修正Django后端的配置和视图
1. 配置跨域支持(关键!)
React运行在127.0.0.1:3000,Django在127.0.0.1:8000,属于不同端口的跨域场景。默认浏览器不会保存跨域请求的Cookie,所以需要通过django-cors-headers库开启跨域携带Cookie的支持:
- 先安装依赖:
pip install django-cors-headers
- 修改
settings.py配置:
# 添加到INSTALLED_APPS INSTALLED_APPS = [ # ... 已有的其他应用 'corsheaders', ] # 添加中间件(注意顺序,必须放在CommonMiddleware之前) MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', # ... 其他中间件 ] # 允许跨域请求携带Cookie CORS_ALLOW_CREDENTIALS = True # 指定允许的前端域名(生产环境禁止用通配符) CORS_ALLOWED_ORIGINS = [ "http://127.0.0.1:3000", ]
2. 修正视图函数
你的contact视图中GET请求直接返回request是错误的,Django视图必须返回HttpResponse或其子类。同时ensure_csrf_cookie装饰器需要配合合法的GET响应才能触发Cookie设置:
from django.views.decorators.csrf import ensure_csrf_cookie from django.http import HttpResponse @ensure_csrf_cookie def contact(request): if request.method == "POST": # 普通Django视图用request.POST获取表单数据,DRF视图才用request.data print(request.POST) return HttpResponse("表单提交成功") elif request.method == "GET": return HttpResponse("CSRF Cookie已设置")
二、修正React前端的Axios代码
1. 全局配置跨域携带Cookie
所有Axios请求都需要开启withCredentials: true,这样浏览器才会保存跨域请求的Cookie,并在后续请求中携带它:
import axios from 'axios'; // 全局配置,避免每个请求重复写 axios.defaults.withCredentials = true;
2. 修复Cookie提取逻辑
你的getCookieValue函数判断逻辑完全写反了,导致无法正确提取csrftoken值,修正如下:
getCookieValue: function(name) { let cookieValue = null; if (document.cookie && document.cookie !== '') { const cookies = document.cookie.split(';'); for (let i = 0; i < cookies.length; i++) { const cookie = cookies[i].trim(); // 检查Cookie是否以目标名称开头 if (cookie.startsWith(name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } console.log("提取到的Cookie值:", cookieValue); return cookieValue; },
3. 解决异步请求顺序问题
getCSRFCookie是异步操作,必须等它完成后再执行POST请求,所以要将其改为返回Promise,并在submitForm中等待它完成:
// 获取CSRF Cookie的函数,返回Promise getCSRFCookie: async function() { console.log("正在获取CSRF Cookie"); try { await axios.get('http://127.0.0.1:8000/customer/contact/'); console.log("CSRF Cookie已接收"); } catch (err) { console.error("获取CSRF Cookie失败:", err); } }, // 提交表单的函数,确保先拿到Cookie再发送请求 submitForm: async function(bodyFormData) { console.log("开始提交表单"); // 先获取CSRF Cookie(如果还未获取) await this.getCSRFCookie(); try { const response = await axios({ method: 'post', url: 'http://127.0.0.1:8000/customer/contact/', data: bodyFormData, headers: { 'Content-Type': 'multipart/form-data', "X-CSRFToken": this.getCookieValue('csrftoken') } }); console.log('请求成功:', response.data); return response.data; } catch (err) { console.error('请求失败:', err.response?.data || err.message); throw err; // 抛出错误方便调用方处理 } }
三、验证步骤
- 重启Django服务器,确保跨域配置生效。
- 在React组件加载时提前获取Cookie,比如在
useEffect中:
import api from './你的API文件路径'; useEffect(() => { api.getCSRFCookie(); }, []);
- 打开Chrome开发者工具,切换到
Application->Cookies->http://127.0.0.1:3000,此时应该能看到csrftokenCookie。 - 提交表单时,检查
Network面板的POST请求,确认X-CSRFToken请求头已正确设置,且Cookie已携带。
额外注意事项
- 如果使用DRF的
APIView,建议直接继承并遵循DRF的CSRF处理逻辑,但当前场景用普通视图加ensure_csrf_cookie完全可行。 - 生产环境禁止设置
CORS_ALLOW_ALL_ORIGINS = True,必须指定具体的前端域名,避免安全风险。 - 若表单没有文件上传,
Content-Type可以用默认的application/x-www-form-urlencoded,Axios会自动处理格式。
内容的提问来源于stack exchange,提问作者Rik Schoonbeek
相关产品推荐
相关产品推荐

