【问题标题】:How should a web application ensure security when serving confidential media files?在提供机密媒体文件时,Web 应用程序应如何确保安全?
【发布时间】:2019-08-11 16:07:13
【问题描述】:

问题:假设用户上传了高度机密的信息。这被放置在第三方存储服务器中。此第三方存储桶对 Web 应用程序使用不同的身份验证系统。确保只有用户或管理员才能访问文件 url 的最佳做法是什么?

更多上下文: Django Web 应用程序在 Google App Engine Flexible 上运行。 Google Storage 用于通过 Django 提供静态和媒体文件。高度机密的信息是护照、法律合同等。

静态文件以相当不安全的方式提供。 /static/ 存储桶是公共的,文件通过 django 的静态文件系统提供。这是因为

  • 我们的任何静态文件中都没有机密或用户信息
    文件,仅库存图片、css 和 javascript,以及
  • 文件在生产前被 uglified 和 minifed。

但是对于媒体文件,我们需要用户特定的权限,如果用户A上传了一张图片,那么用户A可以查看它,工作人员可以查看它,但是用户B和未经身份验证的用户在任何情况下都不能查看它。这包括他们是否有网址。

我的首选系统是,GCP 存储可以使用相同的 django 身份验证服务器,因此当浏览器请求 ...google.storage..../media/user_1/verification/passport.png 时,我们可以检查此用户拥有哪些权限,将其与上传的用户 ID 进行比较,并决定是否显示 403 或实际文件。

此问题的行业标准/最佳实践解决方案是什么?

我是否让这两个存储桶只能由应用程序访问,使用服务帐户,并确保只有在正确的用户正在查看页面时才在内部共享链接? (任何人代表静态,{user or staff} 代表媒体?)

我的问题,特别是(关于网络应用程序安全性):

  1. 从公开可读的存储桶中提供静态文件是否安全?
  2. 是否可以假设如果我的应用程序请求文件 url,它来自经过身份验证的用户?
  3. 特别是关于 Django 和 GCP 存储,如果 2 为假(我相信是),我如何确保从存储桶提供的文件是 只有拥有正确权限的用户才能看到?

【问题讨论】:

  • 这是一个非常广泛的问题,听起来你是在征求人们的意见。你能把它缩小到一个可以或多或少客观地回答的具体问题吗?
  • 我希望在广泛的问题之后使用上下文会降低范围。我将尝试对其进行编辑以降低范围。
  • 您的GCP Storage 是否可以通过 URL 直接访问,或者您是否可以控制它 - 这意味着它只是您代理背后的存储空间?我们使用 X-Accel 从 nginx 传递 Django 的 /media 内容,存储在我们的案例中 Azure 存储中。如果这是您正在寻找的,我可以添加一个答案。见nginx.com/resources/wiki/start/topics/examples/x-accel

标签: django google-app-engine google-cloud-platform google-cloud-storage media


【解决方案1】:
  1. 是的,是的。 Public readable buckets 就是为此而生的。诸如 CSS、您公司的徽标或一些没有敏感数据的文件之类的东西可以安全地共享。

当然,不要使用同一个公共存储桶来存储私有/公共的东西。公共与公共,私人与私人。


  1. 这就是问题所在。当您说“经过身份验证的用户”时,您希望该用户向谁进行身份验证?

例如,如果您使用任何Django methods 对用户进行身份验证,则该用户将通过 Django 身份验证,但对于 Cloud Storage,它将是一个陌生人。此外,即使是在 GCP 上授权的用户也可能无权访问 Cloud Storage 上的存储分区。

这里重要的是,与 Cloud Storage 来回通信的不是用户,而是它的 Django。它可以通过使用python SDK of Cloud Storage 来实现此目的,该python SDK of Cloud Storage 采用实例上正在使用的服务帐户的凭据 来验证对云存储的任何请求。因此,运行虚拟机的service account(因为您处于灵活状态)是应该被授权给 Cloud Storage 的那个。


  1. 您必须首先在 Django 上授权用户,然后检查用户是否能够通过其他方式访问此文件(例如将他上传的文件的名称存储在 user_uploaded_files 表中)。

关于帖子顶部的第一个问题,Cloud Storage 允许您创建signed urls。此 url 允许 Internet 上的任何人只需持有该 url 即可从 Cloud Storage 上传/下载文件。所以你只需要在 Django 上授权用户获取签名的 url 就可以了。他不需要在 Cloud Storage 上获得“授权”(因为 url 已经这样做了)

取自之前链接的文档:

什么时候应该使用签名 URL?

在某些情况下,您可能不会 希望要求您的用户拥有 Google 帐户才能访问 Cloud Storage,但您仍想使用您的 特定于应用程序的逻辑。解决此用例的典型方法 是向用户提供一个签名的 URL,让用户阅读, 在有限的时间内写入或删除对该资源的访问。任何人 知道 URL 的人可以访问资源,直到 URL 过期。你 在要签名的查询字符串中指定过期时间。

【讨论】:

  • 谢谢!这是完美的答案。我整天都在研究解决方案,并且得出了相同的结论。当我遇到您的答案时,我正要自己回答这个问题。无论如何,我都会发布一个答案,其中包含有关我的实施的详细信息。
【解决方案2】:

按照 Nahuel Varela 的回答:

我的系统现在包含 4 个存储桶:

  • 静态
  • 媒体
  • 静态暂存
  • 媒体登台

两个静态存储桶都是公开的,媒体存储桶只能由项目中创建的应用引擎服务帐号访问。 (开发/测试的设置不同)

我正在使用 django-storages[google]@elnygrens modification。我对此进行了修改以删除 Media 的 url 方法(以便我们创建签名 URL),但将其保留为静态(以便我们访问静态文件的公共 URL)。

每个文件访问的身份验证都是在 Django 中完成的,如果用户通过了测试(is_staff 或 id 与文件 id 匹配),那么他们就可以在给定的时间内(当前为 1 小时)访问文件,当页面加载等时,此访问会刷新。

后续问题:这个时间限制的最佳做法是什么,我听说人们使用 15 分钟到 24 小时不等?

【讨论】:

  • 我看到您在答案中发布了一个问题,我建议您打开一个新的 SO 帖子引用这个问题来提出该问题,以便您得到适当的关注。不过,我相信这将取决于每个用例,但对我来说,一小时似乎没问题。
猜你喜欢
  • 1970-01-01
  • 2011-07-19
  • 2012-09-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-21
  • 2011-06-02
  • 2012-07-08
相关资源
最近更新 更多