【问题标题】:Django - Understanding X-SendfileDjango - 了解 X-Sendfile
【发布时间】:2011-11-09 22:21:22
【问题描述】:

我一直在做一些关于使用 Django 进行访问控制的文件下载的研究。我的目标是完全阻止对文件的访问,除非由特定用户访问。我读过在使用 Django 时,X-Sendfile 是实现这一目标的选择方法之一(基于其他 SO 问题等)。我对在 Django 中使用 X-Sendfile 的基本理解是:

  1. 用户请求 URI 以获取受保护的文件
  2. Django 应用根据 URL 决定返回哪个文件,检查用户权限等
  3. Django 应用返回一个 HTTP 响应,其中 'X-Sendfile' 标头设置为服务器的文件路径
  4. Web 服务器找到该文件并将其返回给请求者(我假设 Web 服务器还删除了“X-Sendfile”标头)

与直接从 Django 中获取文件相比,X-Sendfile 似乎可能是实现受保护下载的更有效方法(因为我可以依赖 Nginx 来提供文件,而不是 Django),但给我留下了 2 个问题:

  1. 我对 X-Sendfile 的解释至少在抽象上是正确的吗?
  2. 它真的安全吗,假设我不提供对存储文件的目录的正常前端 HTTP 访问(例如http://www.example.com/downloads/secret-file.jpg)(即,不要将它保存在我的public_html 目录中) ?或者,精通技术的用户是否可以检查标头等并反向工程访问文件(然后分发)的方式?
  3. 性能上真的差别很大吗。我是否会通过直接从 Django 提供 150Mb 文件的 8b 分块下载来使我的应用程序服务器陷入困境,或者这不是问题?我问的原因是,如果两个版本几乎相等,那么 Django 版本会更可取,因为我可以在 Python 中执行操作,例如记录已完成下载的数量、下载的统计带宽等。

提前致谢。

【问题讨论】:

  • 在您上面概述的步骤中,我不清楚一件事:当您说Django app returns an HTTP response with the X-Sendfile header set 时,该回复的接收者是谁?我想这将是 Web 服务器(例如 nginx)。如果是这种情况,是谁发起了由 Django 应用程序处理的请求?
  • @MLister - 用户(网络浏览器) - 基本上,您需要设置一个类似 get_file(request, file_name) 的视图(类似的东西),当用户访问 URL 时,返回响应X-Sendfile 指向命名文件的正确位置(在视图中添加您想要的任何逻辑以确定是否应允许用户下载文件之后)。 Nginx 将在响应输出时拦截响应并返回响应与文件(作为下载)。
  • 所以nginx必须设置在前面Django应用服务器呢?不然nginx怎么能在响应出去的时候拦截呢?
  • @MLister - 没错。例如,您可以使用 Nginx 为您的站点提供静态文件(CSS 等),并将其用作“反向代理”,将请求传递给您的应用程序服务器(例如,uWSGI),然后运行您的 Django 应用程序并获得响应,然后将其返回给 Nginx,由 Nginx 决定做什么(例如,返回响应,或者在 X-Sendfile 的情况下提供下载等)
  • 非常感谢您的澄清!

标签: python django download x-sendfile protected-resource


【解决方案1】:
  1. 是的,它就是这样工作的。
  2. 具体实现取决于网络服务器,但对于 nginx,建议将位置标记为内部以防止外部访问。
  3. Nginx 可以异步处理文件,而使用 Django,每个请求需要一个线程,这对于更多数量的并行请求可能会产生问题。

请记住为 nginx 发送 X-Accel-Redirect 标头而不是 X-Sendfile。 请参阅http://wiki.nginx.org/XSendfile 了解更多信息。

【讨论】: