Amazon web services 如何约束客户端在s3上传时将正确的sha256作为文件密钥发送?(预先签名的url)

Amazon web services 如何约束客户端在s3上传时将正确的sha256作为文件密钥发送?(预先签名的url),amazon-web-services,amazon-s3,aws-sdk,pre-signed-url,aws-sdk-js,Amazon Web Services,Amazon S3,Aws Sdk,Pre Signed Url,Aws Sdk Js,我需要创建一个签名url来将文件上载到s3存储桶。 s3文件密钥应该是它的sha256散列 接下来的问题是:如何确保客户端发送有效的哈希?我在lambda函数中创建签名url,并避免通过它传递文件,因此lambda当然无法计算散列 我想我可以通过两个步骤来实现这一点: 强制客户端在上载时发送其计算的sha256。根据规范,我假设在x-amz-content-sha256标题中提供时,将自动检查此项 强制客户端向lambda发送相同的散列,这样我就可以强制它成为密钥 首先,我试过: s3.getS

我需要创建一个签名url来将文件上载到s3存储桶。 s3文件密钥应该是它的
sha256
散列

接下来的问题是:如何确保客户端发送有效的哈希?我在lambda函数中创建签名url,并避免通过它传递文件,因此lambda当然无法计算散列

我想我可以通过两个步骤来实现这一点:

  • 强制客户端在上载时发送其计算的
    sha256
    。根据规范,我假设在
    x-amz-content-sha256
    标题中提供时,将自动检查此项

  • 强制客户端向lambda发送相同的散列,这样我就可以强制它成为密钥

  • 首先,我试过:

    s3.getSignedUrl('putObject', { Key: userProvidedSha256 }, callback)
    
    我尝试添加一个条件,如
    {header:{'X-Amz-Content-Sha256':userProvidedSha256}

    但是我没有找到添加这样一个定义的方法,因此它实际上会强制客户端发送
    X-Amz-Content-Sha256

    另外,我也会采取同样的方法来强制执行一个固定的required
    Content Length
    头(客户端将所需的长度发送到后端,我们在那里签名),但由于这个原因,我不确定这是否可行

    因为我发现,
    s3.createPresignedPost
    也允许我限制最大附件大小,并且看起来更灵活,所以我选择了这条路线:

    const signPostFile = () => {
      const params = {
        Fields: {
          key: userProvidedSha256
        },
        Expires: 86400,
        Conditions: [
          ['content-length-range', 0, 10000000],
          { 'X-Amz-Content-Sha256': userProvidedSha256]
        ]
      }
    
      s3.createPresignedPost(params, callback)
    }
    
    但是,尽管这样做有效(它强制客户端发送强制sha256头,并且头被传递,请参见下面的请求日志),但看起来客户端现在必须将
    x-amz-content-sha256
    添加到表单字段中,而不是头中。这似乎是有意的,但显然s3不会对照提供的sha256检查提交的文件:即使sha256不匹配,我附加到表单中的任何文件都会成功上载

    有什么问题吗?或者我如何在限制内容长度的同时强制执行sha256条件

    更新:我使用的是signature v4,我尝试了S3策略
    Deny
    ,用于此条件:

    Condition:
      StringEquals:
        s3:x-amz-content-sha256: UNSIGNED-PAYLOAD
    
    提交包含字符串“hello world”的文件的相关请求日志:


    据我所知,S3默认不提供sha256。但是,通过侦听S3事件,您可以实现一个Lambda函数,该函数会自动为您执行此操作。我想到了一个建议:

  • 客户端根据用户提供的sha256请求一个S3签名的url
  • 客户端使用签名的url上载文件
  • Lambda函数被配置为侦听上传bucket中的
    s3:ObjectCreated::
    事件
  • 上传完成后,Lambda函数由。事件的一部分是S3对象键
  • Lambda函数下载上传的文件并重新计算sha256
  • 如果计算的sha256值与客户端提供的sha256值不同(作为对象键或可从对象元数据获得),Lambda函数将删除该文件

  • 或者,如果主要目的是验证上传文件的文件完整性,则S3在计算校验和时提供了另一个使用sha256的选项

  • 将bucket策略配置为
  • 配置客户端AWS S3 sdk以使用AWS签名版本4,例如

    const s3 = new AWS.S3({apiVersion: '2006-03-01', signatureVersion: 'v4'});
    
  • 该函数将在上载文件之前对请求进行签名


  • 如果签名错误,S3将不存储对象,如方法1中所述:这可能有效,但这是否违背了签名URL的目的,即文件不必经过lambda?否则,我可以直接将文件提交给lambda并集中进行检查?方法2:我很难理解这一点。我更新了问题(签名、政策)并简化了您最终是如何处理此问题的?目前正在尝试做同样的事情。还向论坛提出了该功能的请求。
    const s3 = new AWS.S3({apiVersion: '2006-03-01', signatureVersion: 'v4'});