You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django+Docker+SSL:Nginx+Gunicorn栈中如何解决HTTPS下CSRF失效问题?

解决DRF HTTPS配置后POST请求的CSRF错误问题

我帮你梳理下这个问题——当你把DRF返回的图片URL改成HTTPS前缀后,POST请求触发了CSRF错误,但DEBUG=True时一切正常,这本质是生产环境下Django没有正确识别HTTPS请求的上下文,导致CSRF验证逻辑判断出错。下面是不用禁用CSRF中间件或csrf_exempt的解决步骤:

1. 让Django信任Nginx的HTTPS代理头

因为你是用Nginx反向代理Django,Django本身不知道原始请求是HTTPS的,所以需要配置它信任Nginx传递的协议头:

  • 在settings.py中添加:
    SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
    
  • 同时确保ALLOWED_HOSTS包含你的实际域名,比如:
    ALLOWED_HOSTS = ['your-production-domain.com']
    
  • 还要在Nginx的配置里加上这个头的传递,在location块中添加:
    proxy_set_header X-Forwarded-Proto $scheme;
    

2. 配置HTTPS专属的Cookie和CSRF信任源

生产环境下HTTPS需要确保Cookie仅通过安全通道传输,同时告诉Django哪些HTTPS域名是可信的:

  • 在settings.py中设置:
    # 确保CSRF和Session Cookie只通过HTTPS发送
    CSRF_COOKIE_SECURE = True
    SESSION_COOKIE_SECURE = True
    
    # 把你的HTTPS域名加入CSRF信任列表(Django 3.1+必需)
    CSRF_TRUSTED_ORIGINS = ['https://your-production-domain.com']
    
    这里如果你的域名有多个子域名,可以用通配符,比如'https://*.your-domain.com'。

3. 完善Nginx的代理头配置

除了协议头,还要确保Nginx传递其他必要的请求头,让Django能正确识别请求来源:

location / {
    proxy_pass http://your-django-server-ip:port; # 替换成你的Django服务地址
    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获取到真实的请求主机、IP和协议,避免CSRF验证时因为上下文不匹配(比如Django误以为是HTTP请求)而失败。

4. 验证前端的CSRF令牌传递

前端发送POST请求时,必须正确携带CSRF令牌:

  • 从Cookie中读取csrftoken值
  • 在请求头中添加X-CSRFToken: 你的令牌值
    DRF的APIView会自动验证这个头,只要令牌和请求上下文匹配,就能通过CSRF验证。

为什么DEBUG=True时正常?

因为DEBUG模式下Django做了很多宽松处理:ALLOWED_HOSTS可以设为['*']、CSRF信任源的限制被弱化,同时Django会忽略一些代理头的严格校验,所以不会触发错误。但生产环境下这些安全限制都会生效,就暴露了配置缺失的问题。

内容的提问来源于stack exchange,提问作者Vassily

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 07:37:03