浏览器缓存私有 S3 资源

Posted

技术标签:

【中文标题】浏览器缓存私有 S3 资源【英文标题】:Browser Cache Private S3 Resources 【发布时间】:2022-01-15 09:13:48 【问题描述】:

堆栈是:

    角度 Laravel S3 nginx

我正在使用 S3 来存储我的用户的机密资源。存储桶访问权限设置为 private,这意味着我可以通过创建临时(签名、动态)链接或使用 Storage::disk('s3')->get('path/to/resource') 方法并返回实际文件作为响应来访问文件。

我正在寻找一种在用户浏览器中缓存资源的方法。我曾尝试直接在 AWS 上将缓存标头设置为资源响应,但由于我正在创建临时 url,它们是动态的,并且在这种情况下缓存不起作用。

非常感谢任何建议。

编辑:使整个问题更加复杂的一件事是资源的安全性应该完好无损。这意味着我需要一种缓存资源的方法,但同时我必须防止用户复制粘贴链接并在应用程序之外使用它们(通过直接链接与他人共享)。

就安全性而言,临时链接仍然不是一个理想的解决方案,因为它们可以在有效期限内(在我的情况下为 30 秒)内共享(并多次访问)。

【问题讨论】:

您可以采用第二种方法(即“代理”)并在其上设置相应的缓存标头。 @apokryfos 你能更具体一点吗?如果您认为我应该添加缓存头以响应我通过第二种方法返回的文件......我不能使用这种方法,因为我正在使用<img src="path/to/resource"> 加载图像。我不知道我是否遗漏了一些东西,但我真的被困住了,找不到做这种事情并保持资源安全完整的好方法。所以,我基本上需要找到一种方法来返回非动态链接,并且只能由授权用户访问(他不应该只是复制该链接并在应用程序之外重用)。看起来不可能。 您的第二种方法类似于return response(Storage::disk('s3')->get('path/to/resource'), 200, [ headers ]);,它可以使用缓存控制标头,如果要第一次检索图像(或何时检索),您还可以使用会话作为安全手段缓存过期)。 @apokryfos 感谢您的想法。我会尝试一些我可以实际使用该方法的特定情况。 【参考方案1】:

只要 URL 保持不变,缓存将按原样工作(基于 Cache-Control 等)。因此,如果您的应用程序使用相同的签名 URL 一段时间,您会没事的。

当您想要更新到期日期或其他内容时,问题就出现了。这当然有不同的查询字符串参数,实际上是不同的 URL。你需要一个不同的缓存键,但是浏览器默认没有这个概念。

如果您的安全可以接受,您可以创建一个Service Worker,它只使用基本 URL(不带查询字符串)作为缓存键。然后,以后对存储桶上同一对象的请求将能够使用缓存的响应,而不管其他 URL 参数。

我必须阻止用户复制粘贴链接并在应用外使用它们(通过直接链接与他人共享)。

您的这部分要求是不可能的,并且与缓存无关。一旦该 URL 被签名,其他人就可以使用它。

【讨论】:

感谢 Brad 为我指明了新的方向!我通过查看 Service Worker 继续我对这个 缓存 主题的研究,我必须说这是最接近我需要的东西。我很清楚在没有任何定制机制的情况下保护签名 URL 是不可能的,但再次感谢您指出这一点:) How to Cache Files with Service Worker 是我发现的一篇了不起的文章,我会把它放在这里以供将来参考.

以上是关于浏览器缓存私有 S3 资源的主要内容,如果未能解决你的问题,请参考以下文章

HTTP 缓存

从浏览器缓存提供图像时,AWS S3 + CloudFront 会出现 CORS 错误

ceph 对象存储s3

基于Nginx设置浏览器协商缓存过程详解

浏览器缓存知识小结

Amazon s3 静态 Web 托管缓存