【问题标题】:Django: preventing direct access to filesDjango:防止直接访问文件
【发布时间】:2010-10-11 09:19:27
【问题描述】:

我想从我的 web 目录的根目录后面动态地提供文件。目前,我正在静态地提供所有文件,这些文件只是为了包含我的 javascripts 和 css 文件。我意识到这可能很愚蠢,但我无法以任何其他方式提供文件!

所以,我想动态地提供文件,而用户不能在其他时间仅使用 url 访问。

我的设置

ADMIN_MEDIA_PREFIX = '/media/'
MEDIA_ROOT = os.path.join( APP_DIR, 'site_media' )
MEDIA_URL = 'http://localhost:8000/site_media/'

我的网址

( r'^site_media/(?P<path>.*)$', 'django.views.static.serve', { 'document_root': settings.MEDIA_ROOT } )

谢谢!

【问题讨论】:

  • 也就是说,如果用户点击“下载pdf”,django会将文件推送到用户浏览器。用户没有办法回溯和反向 URL 以在将来再次获取文件。

标签: django


【解决方案1】:

“动态”是什么意思?你想达到什么目的?是否要控制对文件的访问?

如果你想运行一些 Django-view 来决定是否允许用户访问文件,你可以使用 sendfile。有关如何设置正确标头的代码,请参见以下 sn-p:http://djangosnippets.org/snippets/2226/

您的网络服务器也需要支持此标头,至少我使用过的 apache 和 nginx 支持。

您还需要考虑如何存储和分发文件,因为运行网络服务器的服务器需要访问文件。这取决于您的设置。

【讨论】:

  • 是的,我想控制对文件的访问。例如,假设我只希望超级用户能够下载特定的 PDF。我想确保用户在允许他们下载文件之前拥有这些凭据。我确实希望允许任何人只去 /some/url.pdf 获取文件而不经过身份验证。
  • 然后使用 web 服务器的 sendfile 功能将是完美的,因为您可以像处理项目其余部分的权限一样处理权限。此解决方案还避免将文件读入您​​的 Django 进程,以便您以后可以将其写回 Web 服务器。
  • 刚刚看到您对您的问题的评论。当您决定是否让用户下载文件时,您可以轻松地做任何您喜欢的事情。例如:此用户之前是否下载过此文件?我应该为每次下载向该用户收费吗?等等。
【解决方案2】:

您可以以一种很难猜到的方式混淆 URL;这一点都不安全,但它会阻止休闲扑克玩家。您还需要确保在生产中用于提供静态媒体的任何内容均未设置为显示目录列表。

如果您需要更安全的东西,这是我过去所做的:

在models.py中:

my_storage = FileSystemStorage(location=settings.MY_FILES_ROOT, base_url='DO_NOT_USE')

class Resource (models.Model):
    //...snip...
    resource_file = models.FileField(storage = my_storage)

其中settings.MY_FILES_ROOT 是您正常保存静态文件的路径之外的路径。

然后,在views.py中:

def get_file(request, whatever_id):
    //check if the user is allowed to access the file here
    resource = Resource.objects.get(id=resid)
    response = HttpResponse(resource.resource_file.read(), mimetype='text/whatever')
    response['Content-Disposition'] = 'attachment; filename=whatever.ext'
    return response

当然,这种方法只有在您知道文件的 MIME 类型和文件扩展名时才有效,无论它始终相同(我在始终提供 PDF 的应用程序中执行此操作)还是从文件中提取它。

【讨论】:

  • URL 混淆很聪明,但并不是我真正想要的。我试图阻止用户直接链接需要身份验证才能查看的文档。
  • 对不起,显然回车键会立即发送您正在编写的内容。您的第二个选项很有趣,是我一直在寻找的东西,但希望有更好的选择。也许这样:djangosnippets.org/snippets/365 是更好的解决方案?感谢您的回复!
  • FileWrapper 听起来是个好主意。 (我应该注意,Content-Disposition 标头(不在那个 sn-p 中)仅在您希望用户下载文件时才需要(而不是在 PDF 的情况下内联或在浏览器插件中查看它/图片/HTML 文件/文本文件/等)。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-04
  • 2016-10-09
  • 2012-05-01
  • 2010-09-29
  • 1970-01-01
相关资源
最近更新 更多