在Django中模拟POST请求时遭遇CSRF Cookie未设置错误求助
问题场景
前端通过Django模板渲染表单(包含{% csrf_token %}),用JS的fetch方法提交POST请求时手动添加X-CSRFToken头;后端视图中使用requests库向/reset接口发送模拟POST请求,已带上get_token(request)获取的CSRF token,但返回Forbidden (CSRF cookie not set.): /reset错误。
解决方案
1. 后端模拟请求需同时携带CSRF Cookie和Token
Django的CSRF验证要求请求必须同时满足:
- 请求Cookie中存在
csrftoken值 - 请求头(
X-CSRFToken)或表单数据中存在与Cookie匹配的CSRF token
之前的代码仅传递了X-CSRFToken头,未携带对应Cookie,导致验证失败。修改后端代码如下:
import requests from django.middleware.csrf import get_token # 创建Session对象自动管理Cookie session = requests.Session() # 先发送GET请求到目标站点,获取CSRF Cookie session.get('http://127.0.0.1:8000/reset') # 构造请求数据 data = {'username': request.user.username, 'form_name': "form1"} # 从Session的Cookie中提取CSRF token csrf_token = session.cookies.get('csrftoken') # 发送POST请求,Session自动携带Cookie,同时传入Token头 response = session.post( 'http://127.0.0.1:8000/reset', data=data, headers={'X-CSRFToken': csrf_token} )
2. 前端JS请求的优化(可选)
若前端也出现同类错误,可优化JS代码,通过浏览器Cookie获取csrftoken并确保请求携带同域Cookie:
// 辅助函数:获取指定名称的Cookie function getCookie(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(); if (cookie.substring(0, name.length + 1) === (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } document.getElementById('form1').addEventListener('submit', function(event) { event.preventDefault(); const form = this; const formData = new FormData(form); formData.append('form_name', 'form1'); fetch(form.action, { method: 'POST', body: formData, headers: { 'X-CSRFToken': getCookie('csrftoken') }, credentials: 'same-origin' // 确保携带同域Cookie }) .then(response => response.json()) .then(data => { if (data.show_form2) showForm2(data); if (data.messages) { const messages = JSON.parse(data.messages); showMessages(messages); } }).catch(error => console.error('Error:', error)); });
内容的提问来源于stack exchange,提问作者ZahRaF
相关产品推荐
相关产品推荐

