AWS从客户端上传文件到S3

Bru*_*que 3 javascript amazon-s3 amazon-web-services node.js

我知道有一些问题.我知道如何使用AWS SDK完成此任务.

但是,我担心的是安全问题.我的计划是生成一个签名的URL,以便用户登录我的网站可以将文件上传到S3.我在服务器端生成此URL(基于Express框架).

问题是:有权访问此URL的任何人都可以将文件上传到我的存储桶.只有登录的用户才能获得这些网址,但任何人都可以使用它们.

有没有办法生成"一次性使用"URL来验证S3?如果没有,是否有一种我可以使用的方法,它不会在客户端显示我的凭据,也不会将文件上传到我的服务器?(我知道,要求太多:/)

poi*_*ida 5

请求需要身份验证

除非您将资源公开写入,否则S3将要求上载请求包含身份验证信息.身份验证将请求绑定到AWS账户,然后检查它是否有权执行针对资源的请求(授权).

有关更多信息,请参阅有关验证请求的AWS文档.

用于生成身份验证信息的算法的最新版本称为"AWS签名版本4".该算法使用帐户的密钥和一些其他数据来产生与请求一起发送的签名.

AWS知道密钥并可以在其末尾重新计算签名.如果签名匹配,则请求被认证为来自该帐户.

AWS开发工具包负责使用提供的帐户凭据为您签署请求.文档描述了算法的工作原理,并告诉您如果您真的想要自己如何签署请求.

在服务器端签署S3请求

您可以代表客户端在服务器上安全地生成签名URL,然后将其返回给他们直接从他们的计算机上调用S3,而不是在客户端保留密钥,以便它可以签署对S3的请求. .

此方案是文档中提到的特定用例之一:

如果您希望您的用户/客户能够将特定对象上传到您的存储桶,但您不需要他们拥有AWS安全凭据或权限,则[P]重新签名的URL非常有用.

创建预签名URL时,必须提供安全凭据,指定存储桶名称和对象密钥,HTTP方法(上载对象的PUT)以及到期日期和时间.

预签名URL仅在指定的持续时间内有效.

预签名请求安全性

预先签名的请求具有烘焙的身份验证签名.如您所述,获取URL的任何人都可以提出请求.但是,我不会让这个事实单独阻止我使用它们; 您可以采取一些措施来防止攻击者使用它.

考虑客户端和服务器之间的以下交互.

直接文件上传到S3序列图

请求到期

使用Expires参数在URL生成时控制到期.通过上述流程,URL可以在生成后几秒钟到期.在此之后,它将不再起作用并被S3拒绝.设置到期时,您需要考虑服务器和用户之间的请求延迟(步骤#5-#7),以及用户和S3(步骤#8).

在签名中包含文件校验和

使用Body参数,您可以指示S3仅允许具有特定MD5校验和的内容.同样,但更安全的是,您可以要求S3 根据文件的SHA256校验和验证有效负载.

在上面的流程中的步骤#3之后,计算文件的SHA256校验和,并在步骤#4中将其传递给服务器.然后,您可以将其添加到请求中,如下所示:

var req = S3.putObject({ Bucket: bucket_name, Key: file_name });
req.on('build', function() {
  req.httpRequest.headers['x-amz-content-sha256'] = file_sha256;
});
var url = req.presign(url_expiry);
Run Code Online (Sandbox Code Playgroud)

(参考文献:AWS.Request类文档,AWS S3服务源代码 - getSignedUrlREST公共请求标头)

获取上传URL应该要求身份验证

只有您的授权用户才能获得预先签名的上传网址.应拒绝匿名请求获取上传URL(步骤#4).

此外,由于这是特权呼叫,因此应审核所有请求(步骤#6).这样,如果预先签名的请求泄露,您就知道是谁生成了它,并且可以在必要时采取进一步措施.

使用HTTPS

有两个主要原因可以保护敏感数据,例如客户端和服务器之间传输时的预签名URL,用户名,密码和会话cookie.

它还向客户保证您是自己所说的人,而不是攻击者设置的虚假网站.