在前后端分离的开发架构中,前端项目和Django后端往往部署在不同的域名下,此时发起跨域请求时,经常会出现CSRF Cookie无法被浏览器正确设置的情况,导致后续需要CSRF校验的请求直接返回403错误。要解决这个问题,需要同时调整Django的CSRF相关配置、跨域CORS配置以及前端的请求参数,三者缺一不可。

问题产生的原因
浏览器出于安全策略,对跨域请求的Cookie设置有严格限制。如果Django后端的跨域配置没有允许携带凭证,或者CSRF Cookie的域名、路径配置不符合跨域要求,浏览器就会拒绝存储服务端返回的CSRF Cookie,进而导致后续请求无法通过CSRF校验。
Django后端配置调整
首先需要修改Django的配置文件settings.py,添加或修改以下配置项:
# settings.py 新增或修改以下配置
# 允许跨域的域名列表,根据实际前端域名填写
CORS_ALLOWED_ORIGINS = [
"http://localhost:3000",
"http://127.0.0.1:3000",
]
# 允许跨域请求携带Cookie
CORS_ALLOW_CREDENTIALS = True
# CSRF Cookie配置,跨域场景下需要设置域名
# 如果是本地开发,可设置为None,生产环境替换为对应域名
CSRF_COOKIE_DOMAIN = None
# 允许CSRF Cookie在跨站请求中携带
CSRF_COOKIE_SAMESITE = None
# 是否使用安全Cookie,本地开发设为False,生产环境HTTPS下设为True
CSRF_COOKIE_SECURE = False
# 中间件中确保CsrfViewMiddleware已启用
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
# 跨域中间件需要放在CommonMiddleware之前
CORS_ALLOW_CREDENTIALS = True
如果使用了django-cors-headers库,还需要确保其版本在3.0以上,低版本可能不支持部分跨域凭证相关的配置。
跨域CORS规则补充
除了基础配置外,还需要针对CSRF相关的请求头做额外允许,避免浏览器拦截携带CSRF Token的请求:
# settings.py 补充CORS允许的请求头和方法
CORS_ALLOW_HEADERS = [
"accept",
"accept-encoding",
"authorization",
"content-type",
"dnt",
"origin",
"user-agent",
"x-csrftoken",
"x-requested-with",
]
CORS_ALLOW_METHODS = [
"DELETE",
"GET",
"OPTIONS",
"PATCH",
"POST",
"PUT",
]
前端请求设置
前端发起请求时,必须显式设置允许携带凭证,否则即使后端配置正确,浏览器也不会处理返回的CSRF Cookie。以下是不同前端场景的示例:
原生Fetch请求示例
// 前端获取CSRF 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;
}
// 发起POST请求示例
fetch('http://127.0.0.1:8000/api/submit/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': getCookie('csrftoken')
},
// 必须设置为true,允许携带Cookie
credentials: 'include',
body: JSON.stringify({ name: 'test' })
})
.then(response => response.json())
.then(data => console.log(data));
Axios请求示例
import axios from 'axios';
// 全局设置允许携带凭证
axios.defaults.withCredentials = true;
// 请求拦截器自动添加CSRF Token
axios.interceptors.request.use(config => {
const csrftoken = document.cookie.replace(/(?:(?:^|.*;s*)csrftokens*=s*([^;]*).*$)|^.*$/, '$1');
if (csrftoken) {
config.headers['X-CSRFToken'] = csrftoken;
}
return config;
});
// 发起请求
axios.post('http://127.0.0.1:8000/api/submit/', { name: 'test' })
.then(response => console.log(response.data));
验证方案
完成上述配置后,可以通过以下步骤验证问题是否解决:
- 打开浏览器开发者工具,切换到Application选项卡,查看Cookie存储列表中是否存在
csrftoken项 - 发起一次GET请求,检查响应头中是否包含
Set-Cookie: csrftoken=xxx; Domain=None; Path=/; SameSite=None的字段 - 发起POST请求,检查请求头中是否携带
X-CSRFToken字段,且请求返回状态为200而非403
如果仍然无法设置Cookie,可以检查浏览器是否开启了阻止第三方Cookie的功能,本地开发时可以暂时关闭该限制,生产环境需要确保域名配置符合浏览器的SameSite策略要求。
DjangoCSRF_Cookie跨域请求CORS配置修改时间:2026-06-09 13:12:26