Web 应用程序在提供机密媒体文件时应如何确保安全性?

How should a web application ensure security when serving confidential media files?

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

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

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

对于媒体文件然而,我们需要用户特定的权限,如果用户A上传图片,那么用户A可以查看,员工可以查看,但是用户B & 未经身份验证用户在任何情况下都无法查看它。这包括他们是否有 url。

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

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

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

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

  1. 从 public 易读存储桶中提供静态文件是否安全?
  2. 是否可以假设如果我的应用程序请求文件 url,这是来自经过身份验证的用户?
  3. 特别是关于 Django 和 GCP 存储,如果 2 为假(我相信它是)我如何确保从存储桶提供的文件是 仅对具有正确权限的用户可见?
  1. 是的,是的。 Public readable buckets 就是为此而生的。 CSS、您公司的徽标或一些没有敏感数据的文件可以安全共享。

当然,不要用同一个Public桶来存储private/public东西。 Public 与 Public,私人与私人。


  1. 问题来了。当您说 "authenticated user" 时,您希望该用户向谁进行身份验证?

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

这里重要的是与云存储来回通信的不是用户,而是 Django。它可以通过使用 python SDK of Cloud Storage, which takes the credentials of the service account that is being used on the instance to authenticate any request to Cloud Storage. So, the service account 来实现这一点,即 运行 VM(因为您处于灵活状态)是应该被授权到 Cloud Storage 的那个。


  1. 你必须首先在 Django 上授权用户,然后检查用户是否能够通过其他方式访问这个文件(比如将他上传的文件的名称存储在 user_uploaded_files table ).

关于 post 顶部的第一个问题,云存储允许您创建 signed urls。此 url 允许互联网上的任何人只需按住 url 即可从云存储 upload/download 文件。所以你只需要在Django上授权用户获取签名的url就可以了。他不需要在云存储上 "authorized"(因为 url 已经做到了)

摘自之前链接的文档:

When should you use a signed URL?

In some scenarios, you might not want to require your users to have a Google account in order to access Cloud Storage, but you still want to control access using your application-specific logic. The typical way to address this use case is to provide a signed URL to a user, which gives the user read, write, or delete access to that resource for a limited time. Anyone who knows the URL can access the resource until the URL expires. You specify the expiration time in the query string to be signed.

继 Nahuel Varela 的回答之后:

我的系统现在由 4 个桶组成:

  • 静态
  • 媒体
  • 静态分期
  • 媒体登台

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

我正在使用 django-storages[google]。我修改了它以删除媒体的 url 方法(以便我们创建带符号的 URLS)但保留它用于静态(以便我们访问 public URL静态文件)。

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

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