
Django 在启用 HTTPS 后出现 CSRF verification failed 错误,通常源于 Nginx 反向代理配置缺失关键头信息、CSRF 设置与 HTTPS 不兼容,或 CSRF_TRUSTED_ORIGINS 未正确配置。本文系统梳理排查路径与修复方案。
django 在启用 https 后出现 csrf verification failed 错误,通常源于 nginx 反向代理配置缺失关键头信息、csrf 设置与 https 不兼容,或 `csrf_trusted_origins` 未正确配置。本文系统梳理排查路径与修复方案。
当 Django 应用从 HTTP 迁移至 HTTPS(尤其在 Docker + Nginx + AWS EC2 的生产环境中),常遇到 403 Forbidden: CSRF verification failed 错误——即使模板中已正确使用 {% csrf_token %},且后端逻辑无变更。该问题并非 CSRF Token 生成或提交本身失效,而是 Django 无法正确识别请求来源的可信性与安全上下文,核心原因集中在三方面:Nginx 代理头转发缺失、Django 安全配置未适配 HTTPS、以及跨域与信任源设置不严谨。
✅ 关键修复步骤
1. 补全 Nginx 反向代理头(最常见原因)
默认 Nginx 配置若仅包含基础 proxy_pass 和 Host/X-Forwarded-For,将导致 Django 无法获知原始协议(https)及真实客户端 IP,进而拒绝 CSRF Token 校验。必须显式传递 X-Forwarded-Proto:
location / {
proxy_pass http://127.0.0.1:8000; # 或你的 Gunicorn/Uvicorn 地址
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme; # ? 必须添加!告知 Django 当前是 HTTPS
proxy_set_header X-Forwarded-Host $server_name;
}⚠️ 注意:$scheme 在 HTTPS 请求中值为 https,Django 依赖此头判断是否启用 CSRF_COOKIE_SECURE 策略。
2. 修正 Django settings.py 安全配置
原配置中存在两个严重问题:
- CSRF_TRUSTED_ORIGINS 包含 http://localhost/(HTTP 协议),但生产环境已启用 HTTPS,且该条目末尾斜杠 / 是非法格式;
- CORS_ORIGIN_WHITELIST 已被弃用(DRF 3.13+),应改用 CORS_ALLOWED_ORIGINS,且协议必须匹配(HTTPS)。
修正后的推荐配置(生产环境):
# settings.py
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') # ? 显式启用代理 SSL 识别
CSRF_COOKIE_SECURE = True # 仅通过 HTTPS 发送 CSRF Cookie
SESSION_COOKIE_SECURE = True # 同理,确保 Session Cookie 安全
SECURE_SSL_REDIRECT = True # 强制 HTTP → HTTPS 重定向(可选但推荐)
# ✅ 正确格式:协议 + 域名(无路径,无尾部斜杠)
CSRF_TRUSTED_ORIGINS = [
'https://example.co.in',
'https://www.example.co.in',
'https://localhost:8080', # 开发时如需本地 HTTPS 测试
]
# ✅ DRF CORS 配置(替代已废弃的 CORS_ORIGIN_WHITELIST)
CORS_ALLOWED_ORIGINS = [
'https://example.co.in',
'https://www.example.co.in',
]
CORS_ALLOW_CREDENTIALS = True # 若前端携带 cookies(如 axios withCredentials: true)3. 验证与调试建议
- 清除浏览器缓存与 Cookie:旧的 HTTP 版本 CSRF Cookie 可能残留,导致冲突;
- 检查浏览器开发者工具 → Application → Cookies:确认 csrftoken Cookie 的 Secure 属性已生效(仅 HTTPS 传输);
-
临时启用 Django 日志,在 settings.py 中添加:
LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': {'console': {'class': 'logging.StreamHandler'}}, 'loggers': {'django.security.csrf': {'handlers': ['console'], 'level': 'DEBUG'}}, }可定位具体拒绝原因(如 Referer checking failed 或 Origin checking failed)。
总结
CSRF 403 错误在 HTTPS 迁移后高频出现,本质是安全上下文链断裂:Nginx 未透传协议信息 → Django 误判请求不安全 → 拒绝校验 Token。解决需三方协同:Nginx 补全 X-Forwarded-Proto、Django 启用 SECURE_PROXY_SSL_HEADER 并严格配置 CSRF_TRUSTED_ORIGINS(HTTPS 协议 + 无路径)、前端确保 fetch/axios 请求 Origin 与配置一致。完成上述调整后,无需修改业务代码即可恢复正常 CSRF 验证流程。










