生产环境Django CSRF Token无法存入浏览器Cookie问题求助
问题排查与解决方案
核心原因分析
生产环境下CSRF Token未写入浏览器Cookie,主要和Azure Front Door的代理配置、iframe跨域Cookie限制以及Django的信任源配置有关——开发环境无代理且跨域限制宽松,因此未出现问题。
分步解决方案
1. 修正Azure Front Door代理配置
Azure Front Door默认可能过滤或修改响应头,需确保:
- 允许传递
Set-Cookie头,包含csrfmiddlewaretoken的Cookie必须能正常透传 - 配置缓存规则,禁止缓存包含CSRF Token的页面(如
base.html),避免Token过期或不更新 - 确认Front Door与App Service之间使用HTTPS协议:
CSRF_COOKIE_SECURE = True要求Cookie仅在HTTPS环境下传递,若代理层用HTTP,Cookie无法写入
2. 完善Django的CSRF配置
当前配置基础上补充以下项:
- 添加
CSRF_COOKIE_HTTPONLY = False:虽然你通过模板变量注入Token,但确保Cookie能被浏览器正常存储需关闭HTTPONLY限制 - 配置
CSRF_TRUSTED_ORIGINS,包含Front Door和App Service的域名:
这是关键:Django必须信任代理过来的请求来源,否则不会生成并返回CSRF Cookie。CSRF_TRUSTED_ORIGINS = [ 'https://你的FrontDoor域名.com', 'https://你的AppService域名.azurewebsites.net' ]
3. 优化AJAX请求逻辑
- 替换模板变量注入Token的方式,改为从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; } const csrf_token = getCookie('csrftoken'); - 修复AJAX请求的参数冲突:代码同时写了
type: 'GET'和method: 'POST',会导致请求方法混乱,删除type字段,保留method: 'POST'
4. 验证iframe跨域权限
Shopify iframe嵌入场景下,需确保页面响应头包含:
Permissions-Policy: interest-cohort=(), cross-origin-isolated=()
同时确认你的域名已添加到Shopify应用配置的有效重定向URL列表中,避免Shopify限制未授权域名的嵌入。
5. 调试Cookie写入过程
打开浏览器开发者工具排查:
- 查看Network面板,加载
base.html时的响应头是否存在Set-Cookie: csrftoken=xxx; Secure; SameSite=None; ... - 若无该响应头:检查
CSRF_TRUSTED_ORIGINS配置是否正确,Django未生成Cookie - 有响应头但浏览器未存储:检查浏览器隐私设置(如第三方Cookie阻止)或插件是否拦截了跨域Cookie
临时替代方案(不建议长期使用)
若以上步骤暂时无法生效,可用@csrf_protect替代@csrf_exempt,同时手动强化Token验证:
from django.middleware.csrf import get_token from django.http import JsonResponse @csrf_protect def your_view(request): if request.method == 'POST': token = request.headers.get('X-CSRFToken') if not token or token != get_token(request): return JsonResponse({'error': '无效的CSRF Token'}, status=403) # 业务逻辑代码 return JsonResponse({'status': 'ok'})
内容的提问来源于stack exchange,提问作者Ross
相关产品推荐
相关产品推荐

