React+Django中Axios POST请求CSRF验证失败问题求助
我之前也遇到过一模一样的问题,折腾了好一阵子才搞定,结合你的代码和情况,给你几个关键的解决步骤:
1. 先修正Django视图的JSON解析问题
你当前的视图用了request.POST['username'],但Axios发送的是Content-Type: application/json格式的数据——Django的request.POST只能解析application/x-www-form-urlencoded或multipart/form-data类型的请求体,JSON数据需要从request.body中读取并解析。修改你的视图代码:
import json from django.http import JsonResponse def createUser(request): if request.method != 'POST': return JsonResponse({'error': 'Method not allowed'}, status=405) # 解析JSON请求体 try: data = json.loads(request.body) except json.JSONDecodeError: return JsonResponse({'error': 'Invalid JSON'}, status=400) username = data.get('username') email = data.get('email') resp = { 'username': username, 'email': email } return JsonResponse(resp)
2. 确保Axios的CSRF配置正确生效
你已经设置了xsrfHeaderName和xsrfCookieName,但还缺了一个关键配置:跨域请求时携带Cookie。默认情况下,Axios在跨域请求时不会发送Cookie,而Django的CSRF Token是存在Cookie里的,所以必须开启withCredentials:
方式一:全局配置(推荐)
在你的React项目入口文件(比如index.js)里添加:
import axios from 'axios'; // 全局配置Axios axios.defaults.withCredentials = true; axios.defaults.xsrfHeaderName = "X-CSRFTOKEN"; axios.defaults.xsrfCookieName = "csrftoken";
方式二:单个请求配置
如果不想全局开启,也可以在每个POST请求里单独设置:
axios.post('http://localhost:8000/api/createUser/',{ username : 'xyz', email : 'xyz@gmail.com' }, { headers: { 'Content-Type': 'application/json', }, withCredentials: true // 关键配置 });
3. 配置Django的CORS(跨域资源共享)
如果你的React项目运行在localhost:3000,Django在localhost:8000,属于跨域场景,需要安装并配置django-cors-headers来允许跨域请求携带Cookie:
- 安装依赖:
pip install django-cors-headers
- 修改
settings.py:
INSTALLED_APPS = [ # ... 其他应用 'corsheaders', ] MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', # 放在最前面 'django.middleware.common.CommonMiddleware', # ... 其他中间件,确保CsrfViewMiddleware在里面 'django.middleware.csrf.CsrfViewMiddleware', ] # 允许的前端域名 CORS_ALLOWED_ORIGINS = [ "http://localhost:3000", ] # 允许携带Cookie CORS_ALLOW_CREDENTIALS = True # 配置CSRF Cookie的SameSite属性(根据你的环境调整) CSRF_COOKIE_SAMESITE = 'Lax' SESSION_COOKIE_SAMESITE = 'Lax' # 如果是HTTPS环境,需要开启下面两个配置 # CSRF_COOKIE_SECURE = True # SESSION_COOKIE_SECURE = True
4. 验证CSRF Token是否正确携带
发送请求前,打开浏览器的开发者工具(F12),切换到Network标签,找到你的POST请求:
- 检查Request Headers里是否有
X-CSRFTOKEN字段,且值和Cookie里的csrftoken一致; - 检查Cookies里是否存在
csrftoken。
如果没有csrftokenCookie,可以通过一个单独的Django视图获取Token:
from django.middleware.csrf import get_token from django.http import JsonResponse def get_csrf_token(request): return JsonResponse({'csrfToken': get_token(request)})
然后在React里先请求这个接口拿到Token,再手动设置到Axios的headers里:
axios.get('http://localhost:8000/api/get-csrf-token/') .then(response => { const csrfToken = response.data.csrfToken; axios.post('http://localhost:8000/api/createUser/', { username: 'xyz', email: 'xyz@gmail.com' }, { headers: { 'X-CSRFTOKEN': csrfToken, 'Content-Type': 'application/json' }, withCredentials: true }); });
按照这些步骤调整后,你的CSRF验证应该就能通过了,同时视图也能正确解析JSON数据。
内容的提问来源于stack exchange,提问作者Andro

