使用预签名 URL 上传到 Amazon S3 时限制对象大小

Posted

技术标签:

【中文标题】使用预签名 URL 上传到 Amazon S3 时限制对象大小【英文标题】:Limit Size Of Objects While Uploading To Amazon S3 Using Pre-Signed URL 【发布时间】:2014-11-17 10:25:10 【问题描述】:

我知道使用这种方法限制对象的上传大小:http://doc.s3.amazonaws.com/proposals/post.html#Limiting_Uploaded_Content

但我想知道如何以 IAM 用户身份在服务器端使用 S3 SDK 生成预签名 url。

这个来自 SDK 的 Url 在其参数中没有这样的选项:http://docs.aws.amazon.com/AWSjavascriptSDK/latest/AWS/S3.html#putObject-property

这两个都不是: http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getSignedUrl-property

请注意:我已经知道这个答案:AWS S3 Pre-signed URL content-length 这不是我想要的。

【问题讨论】:

不,我最终改用 S3 策略进行 HTTP POST。 - 链接:docs.aws.amazon.com/AmazonS3/latest/API/… @Koder 您最终是否使用了预签名 URL + HTTP Post 策略的组合?如果是,您可以将其发布为答案吗?对我有帮助! @NikhilPatil - 不知道你所说的组合是什么意思。在上传过程中,我将 http post 策略返回给浏览器。浏览器使用该策略上传文件。当链接文件以供最终用户使用时,我会生成一个预签名的 URL,因为必须保护该文件不被匿名使用(我在生成时配置了 url 超时)。但我在上传过程中不使用预签名的网址。 @Koder 是的,你回答了我的问题 :) 我试图在浏览器上传中使用预签名的 url。并且要限制想要指定策略的大小,是不可能的。即使我已经得出结论,你最终做的是最好的方法。谢谢!这很有帮助 我很惊讶,AWS 没有安排使用预签名 URL 限制最大上传大小 【参考方案1】:

对于最终出现在此线程上的任何其他流浪者 - 如果您在从客户端发送请求时设置 Content-Length 属性,则有几种可能性:

    Content-Length 是自动计算的,S3 每个文件最多可以存储 5GB

    Content-Length 由您的客户端手动设置,这意味着将发生以下三种情况之一:

Content-Length 与您的实际文件大小相匹配,并由 S3 存储。 Content-Length 小于您的实际文件大小,因此 S3 将截断您的文件以适应它。 Content-Length 大于您的实际文件大小,您将收到 400 Bad Request

在任何情况下,恶意用户都可以覆盖您的客户端并手动发送 HTTP 请求,其中包含他们想要的任何标头,包括比您预期的大得多的 Content-Length。签名的 URL 不能防止这种情况!唯一的方法是设置 POST 策略。官方文档:https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-HTTPPOSTConstructPolicy.html

更多详情:https://janac.medium.com/sending-files-directly-from-client-to-amazon-s3-signed-urls-4bf2cb81ddc3?postPublishedType=initial

或者,您可以使用 Lambda 自动删除比预期大的文件。

【讨论】:

为什么说签名 URL 不能防止更改包含在签名中的标头字段? @user1055568 因为即使您在创建签名 URL 时指定标头作为参数,它仍然会接受没有匹配标头的请求。可以看详细解释here。 我相信你是不正确的。 V4 签名协议允许在签名中包含 ContentLength。可能有些库不支持这个,提醒大家注意一下。 @user1055568 是的,您可以将 ContentLength 作为参数包含在内,对此我不同意您的看法。我具体说的是强制 ContentLength。因此,即使在创建预签名 S3 URL 期间,您可以包含 ContentLength,并且它将在标头映射中返回指定的 ContentLength,但没有什么可以阻止客户端覆盖 ContentLength 标头并将其发送到您的预签名 URL,这将使用覆盖的 ContentLength 处理请求。我建议您尝试使用 Postman 来说服自己。祝你好运! :) 您用于创建签名的工具必须被破坏,因为它不包括签名中的 ContentLength。建议您查看有关如何在签名中包含标头的 Amazon 文档。【参考方案2】:

您可能无法事前限制内容上传大小,尤其是考虑到 POSTMulti-Part 上传。您可以使用AWS Lambda 创建事后解决方案。您可以设置Lambda 函数来接收来自S3 存储桶的通知,让函数检查对象大小并让函数删除对象或执行其他操作。

这里有一些关于 Handling Amazon S3 Events Using the AWS Lambda.

【讨论】:

对于其他不理解的人:“ex-ante 一词(有时写成 ex ante 或 exante)是一个短语,意思是“在事件发生之前”。【参考方案3】:

V4 签名协议提供了在签名中包含任意标头的选项。看: http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html 因此,如果您事先知道确切的 Content-Length,则可以将其包含在签名 URL 中。根据 CURL 的一些实验,如果您发送的文件超过 Content-Length 标头中指定的内容,S3 将截断文件。这是一个示例 V4 签名,签名中有多个标头 http://docs.aws.amazon.com/general/latest/gr/sigv4-add-signature-to-request.html

【讨论】:

如果您发送的 less 比标头中指定的要少,会发生什么?请求是否被接受,如果接受,是否在 S3 上更新内容长度? @julealgon 它将返回 400 错误请求。 ContentLength 通常在发送请求时确定,因此如果您手动指定大于实际文件大小的 ContentLength,S3 会将其视为格式错误的请求。

以上是关于使用预签名 URL 上传到 Amazon S3 时限制对象大小的主要内容,如果未能解决你的问题,请参考以下文章

Amazon S3 预签名 URL - 手动或一次性上传无效

如何使用预签名的 url 将对象放入 amazon s3?

如何使用 amazon sdk 为虚域生成预签名的 Amazon S3 url?

Amazon s3 预签名 URL 受 IP 地址限制

Android 中 Amazon S3 预签名 URL 的改进

带有预签名 URL 和 CORS 问题的 S3 上传