GCP Cloud Run上Django+React的Stripe支付POST请求403错误问题
Django + React跨域CSRF 403问题解决方案(Stripe支付场景)
问题核心
跨域场景下(React部署在GitHub Pages,Django后端在GCP),提交Stripe支付POST请求时触发403,日志提示Forbidden (CSRF cookie not set.): /api/create-payment-intent/。虽已设置X-CSRFToken请求头、withCredentials并手动写入cookie,但CSRF验证仍失败,禁用csrf_exempt可正常请求但存在安全风险。
针对性解决方案
1. 修正CSRF_COOKIE_DOMAIN配置
你的后端部署在xxx.run.app域名,但当前CSRF_COOKIE_DOMAIN设为前端域名owenmitchell.github.io,这是核心错误:
- Django的CSRF cookie由后端生成,只能绑定自身域名(或其父域名),无法直接设置前端域名的cookie(跨域场景下浏览器会阻止)。
- 修改配置:
# 注释或删除原CSRF_COOKIE_DOMAIN设置,让浏览器自动处理 # CSRF_COOKIE_DOMAIN = 'owenmitchell.github.io'
2. 让后端自动设置CSRF cookie,放弃手动写入
当前你通过GET接口获取token后手动设置cookie,这种方式生成的cookie不符合后端的域名规则,浏览器在POST请求时不会携带。正确做法是:
- 保留
get_csrf视图,但无需返回token(Django会在GET请求时自动设置CSRF cookie):def get_csrf(request): # 只需触发Django自动设置CSRF cookie,无需返回token return JsonResponse({"status": "ok"}) - 前端代码改为从浏览器自动生成的cookie中提取token:
axios.defaults.withCredentials = true; // 发起GET请求,触发后端设置CSRF cookie await axios.get("https://xxx.run.app/api/get-csrf"); // 从浏览器cookie中提取csrftoken(Django默认的cookie名称) const csrfToken = document.cookie.split('; ') .find(row => row.startsWith('csrftoken='))?.split('=')[1]; axios.defaults.headers.common['X-CSRFToken'] = csrfToken; - 删除
Cookies.set('csrftoken', csrfToken);这行手动设置cookie的代码。
3. 验证Cookie名称一致性
Django仅识别名为csrftoken的CSRF cookie,确认document.cookie中存在的是csrftoken而非csrfcookie(你的描述中存在名称不一致的问题),若为拼写错误需立即修正。
4. 确认中间件顺序
确保CORS中间件在CSRF中间件之前加载,保证跨域预检请求先被处理:
MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', # 其他中间件... ]
5. 检查CSRF_TRUSTED_ORIGINS完整性
确保列表中包含前端完整域名(带协议头):
CSRF_TRUSTED_ORIGINS = [ "https://owenmitchell.github.io", 'http://localhost:3000', "http://127.0.0.1:3000" ]
内容的提问来源于stack exchange,提问作者Owen Mitchell
相关产品推荐
相关产品推荐

