基于浏览器的上传 - AWS S3签名POST - 验证上传的文件是否正确

时间:2017-05-20 14:40:29

标签: javascript amazon-web-services amazon-s3

我试图了解如何通知后端用户已将文件上传到s3,其密钥并阻止用户篡改密钥。

要上传的文件是私有的,这意味着我正在生成签名的GET URL以在用户需要时下载文件。 我正在使用boto3来创建预先指定的POST URL,所以我没有使用自制的实现,但这与库无关。

我有一个javascript前端和一个后端API,上传文件的用户流程可能会更多或更少:

  • 浏览器 - > API(GET / sign):
    • 请求:
      • {
          filename: 'something.txt
          size: 12345
          type: image/jpeg
        }
        
    • 响应:
      • 使用文件名的后端计算随机密钥(以避免冲突),然后使用ACCESS_KEY,SECRET_KEY,BUCKET_NAME和更多信息计算签名,将所需参数发送回前端< / LI>
      • 后端不会在其数据库中保存任何数据,因为在客户端上传文件之前没有实际数据。
      • {
            url: https://mybucket.s3.amazonaws.com
            fields: {
                acl: 'private',
                key: 'mykey', 
                signature: 'mysignature', 
                policy: 'mybase64 encoded policy'
            }
        }
        
  • 浏览器 - &gt; s3(POST mybucket.s3.amazonaws.com):

    • 请求:

      • 浏览器将实际文件和签名参数作为multipart / form-data
      • 发送
      • {
                acl: 'private',
                key: 'mykey', 
                signature: 'mysignature', 
                policy: 'mybase64 encoded policy'
        }
        
    • 响应(文档aws RESTObjectPOST):

      • 在标题和正文中我们有:
        • 铲斗
        • 关键
        • ETag(“是对象的MD5哈希”)
        • 位置

许多JavaScript库和指南(即FineUploaderHeroku)现在只需将POST响应中的密钥代理到后端。然后后端检查文件是否存在,并将新文件密钥添加到其数据库中。

现在,要上传的文件是私有的,这意味着我正在生成签名的GET URL以在用户需要时下载文件。 假设 UserA UserB UserB 已上传 FileB 。 是什么阻止UserA上传文件,但是向后端发送FileB密钥(可以猜到或者只是随机输入,直到它们存在某些东西),从而后端保存userA有fileB?

我的意思:

  • 键是随机的,键/文件只能属于一个用户,因此当userA告诉“我已经上传了fileB”时,后端响应“fileB是另一个用户”/“错误”。在我看来这是解决问题的最简单方法,但我认为我遗漏了一些东西(并发,剩余文件......)
  • 在GET /签名后端存储“UserA将上传FileA”,因此在回调时后端检查UserA是否想要上传FileA,如果不匹配“错误”
  • 检查s3返回的ETag,以便他们必须拥有该文件来计算其md5,并且用户无法获取FileB。
  • 在策略中设置密钥为XXXX,并在回调中重新计算签名并检查其是否相同。
  • 使用临时上传存储桶,以便恶意用户不仅需要猜测随机密钥,还需要此密钥是现在正在上传的文件。当调用回调时,后端将具有指定键的文件移动到最终存储桶。

也许我忽略了一些东西,但除了(我认为)hacky之外我找不到任何在线解决方案(设置密钥以用户名开头......)。

我不能发布两个以上的链接,因此遗漏了一些aws文档。

0 个答案:

没有答案