亚马逊S3预签名URL

6
如果我设置我的应用程序生成预签名URL以访问S3媒体文件(这样我就可以将文件设置为私有,除非通过已登录的用户访问),那么如果某人在过期时间内拥有URL访问权限,他们可以看到该文件,尽管它是“私有”的,你认为我的理解正确吗?
所以,如果有人向别人发送URL,那么它就不再是私有的了。
我想没有其他方法,但这对我来说似乎很奇怪。

然后,您应该做一些像使用带有url的标题值(对于已登录用户)的内容,以便他们可以查看url并分享给其他人。但是,在服务器获得标题值之前,它不会提供图像。 - Sulthan Allaudeen
2个回答

8

是的,您说得对,签名URL可以被“共享”,因为它在到期之前有效(或者在签名它的凭据到期或无效时,以先到者为准)。

一种常见的解决方案是在页面呈现时,您的应用程序生成带有非常短过期时间的签名URL。

另一种解决方案是将安全内容的链接实际上作为返回到应用程序的链接,该应用程序验证用户访问对象的权限,然后返回一个HTTP重定向到具有短过期时间(例如5秒)的新生成的签名URL。

HTTP/1.1 302 Found
Location: https://example-bucket.s3.amazonaws.com/...?X-Amz-...

签名 URL 无法被当前可行的计算能力篡改,因此恶意用户修改签名 URL 在实际上是不切实际甚至不可能的。

还要注意的是,签名 URL(无论是 S3 还是 CloudFront)仅在下载 开始 时需要未过期。下载实际上完成所需的时间可以任意长,且下载不会中断。

以下选项没有现成的服务,但是通过使用 CloudFront Lambda@Edge 触发器和 DynamoDB 的组合,可以创建一个真正的一次性 URL,其中包含在 Dynamo 表中存储的随机生成的“令牌”,并与目标对象相关联。当访问该 URL 时,您可以在 Lambda 触发器中使用 DynamoDB 条件更新将(例如)“view_count”值从 0 更新为 1。如果表中不存在该令牌或查看计数不为 0,则条件更新失败,因此拒绝访问;否则,CloudFront 允许请求继续进行 - 正好一次。CloudFront 使用 Origin Access Identity 访问 S3 内容,所有这些都在幕后完成,因此与 CloudFront 和 S3 之间的实际身份验证相关的任何内容都无法被用户访问。(对于加密质量的随机令牌生成,您还可以使用 KMS 的 GenerateRandom API 操作。)
有许多替代方法,包括使用 Lambda@Edge 触发器的其他用途,例如检查应用程序提供的 cookie 的请求,然后查询应用程序服务器以对用户进行身份验证。
CloudFront还支持签名cookie,它自己解析和解释,但是这些提供基于通配符的访问权限,匹配特定URL和路径的所有资产(例如/images/*),没有任何防止用户共享其cookie的方法,因此对于您的用例可能没有用处。
CloudFront签名URL确实支持选项,只允许在使用签名URL的情况下从特定源(客户端)IP地址访问,但是如果不存在用户和IP地址之间的1:1关联,则存在潜在问题。许多用户可以位于同一地址后面(特别是在企业网络环境中),或者单个用户的地址随时可能发生变化。
可能实现的复杂性差异很大,您需要的取决于您需要内容有多安全。在许多情况下,更极端的解决方案几乎没有起到更多作用,因为用户仍然可以下载资源并通过其他方式共享它。

-4

当我说“已登录用户”时,我的意思是“已登录到我的网站”。我不是在谈论S3用户。因此,如果已登录到我的网站的某个人点击链接以访问私有文档,则会使用我的S3凭据获取签名URL,理论上,他们可以将其转发给未登录到我的网站的朋友。 - bodger
您的网站需要使用标头验证对对象的访问。如果其他用户使用不正确的标头值提供URL,则将不再具有有效签名并且无法访问该对象。 - EFeit
当然,我将S3文件隐藏在我的网站URL后面,并为该URL设置权限检查,以防止未经身份验证的访问。明白了。我想是这样。谢谢。 - bodger
1
抱歉,@EFeit,这不正确。我不确定你在想什么,因为无论是S3还是CloudFront签名的GET请求URL都不会导致服务检查任何标头。 - Michael - sqlbot
请在您的答案中包含代码和说明。请避免将人们引导到外部网站。一旦您有足够的声望,您就可以提供带有此类信息的评论。 - jww

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接