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

Django+Gunicorn+Nginx环境下CSRF验证失败及大文件上传求助

解决Django+Gunicorn+Nginx大文件上传CSRF验证失败问题

我之前调试类似的Django大文件上传场景时,也碰到过小文件正常、大文件触发CSRF验证失败的情况。结合你已经配置了CSRF中间件和表单token的前提,大概率是大文件上传过程中请求缓冲区不足、Cookie传递异常或者请求解析中断导致的,给你几个针对性的排查和解决步骤:

1. 先看Django的CSRF详细日志,定位具体失败原因

别瞎猜,先通过日志明确问题根源。在settings.py里添加CSRF相关的日志配置:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.security.csrf': {
            'handlers': ['console'],
            'level': 'DEBUG',
            'propagate': False,
        },
    },
}

重启服务后上传大文件,查看控制台日志:

  • 如果显示CSRF cookie not set:说明Cookie没传到Django,大概率是Nginx或浏览器的问题
  • 如果显示CSRF token missing or incorrect:可能是表单token和Cookie里的token不匹配,或者请求体解析异常

2. 调整Nginx的请求缓冲区配置(关键!)

大文件上传时,Nginx默认的缓冲区可能不够用,导致请求头(包括CSRF Cookie)无法完整传递给Gunicorn。在你的Nginx server配置块里添加以下参数:

# 增大请求缓冲区,确保CSRF Cookie和请求头能完整传递
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;

# 再次确认文件大小限制(确保配置生效)
client_max_body_size 100M; # 改成你需要的最大文件大小

修改后重启Nginx:sudo systemctl restart nginx

3. 检查AJAX上传的CSRF头(如果用前端异步上传)

如果你是用JavaScript(比如AJAX、Fetch)上传大文件,别只依赖表单里的csrf_token字段,一定要在请求头里主动带上X-CSRFToken:

// 获取页面里的CSRF token
const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]').value;
const formData = new FormData();
formData.append('file', document.getElementById('file-input').files[0]);

// 发起上传请求
fetch('/your-upload-endpoint/', {
    method: 'POST',
    headers: {
        'X-CSRFToken': csrfToken,
        // 不要手动设置Content-Type!FormData会自动处理multipart/form-data
    },
    body: formData
});

注意:手动设置Content-Type会破坏FormData的边界符,导致Django无法正确解析请求体,进而拿不到CSRF token。

4. 调整Django的CSRF Cookie配置

如果你的网站用HTTPS,确保CSRF Cookie的安全设置正确,避免大文件上传时Cookie丢失:

# settings.py
CSRF_COOKIE_SECURE = True  # 仅在HTTPS下传递Cookie,适合生产环境
CSRF_COOKIE_HTTPONLY = False  # 如果用前端JS上传,必须设为False,否则JS拿不到Cookie
CSRF_COOKIE_SAMESITE = 'Lax'  # 同域上传用Lax即可,跨域的话改成None(需配合CSRF_COOKIE_SECURE=True)

5. 优化Gunicorn的Worker配置

大文件上传是长连接操作,如果用Gunicorn默认的sync worker,可能会因为连接阻塞导致请求中断,进而触发CSRF验证失败。建议换成异步worker,比如gevent:

# 先安装gevent
pip install gevent
# 启动Gunicorn时指定worker类
gunicorn --worker-class=gevent --workers=4 --timeout=120 your_project.wsgi:application

异步worker能更好地处理长连接,避免请求中途断开。

6. 最后验证表单的CSRF Token位置

虽然理论上位置不影响,但可以试试把{% csrf_token %}放在<form>标签内的第一行,确保浏览器优先解析这个字段:

<form method="POST" enctype="multipart/form-data">
    {% csrf_token %}
    <input type="file" name="file">
    <button type="submit">上传</button>
</form>

按这个顺序排查,基本能解决大文件上传的CSRF问题。先看日志定位原因,再针对性调整配置,效率会更高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:41:15