即使通过POST将相同文件上传到Amazon S3,随机“SignatureDoesNotMatch”也会禁止请求

时间:2014-01-28 02:45:06

标签: ruby amazon-s3 jquery-file-upload

我多次上传同一个文件“File.txt”。有时它会成功上传到S3,有时会提升:

SignatureDoesNotMatchThe request signature we calculated does not match the signature you provided. Check your key and signing method

我不知道要测试什么来发现问题。这个例外是否真的是一个政策+签名问题?那么为什么我有时可以上传?

在升级到Rails 4并更新一些库之前,相同的配置始终有效。 但是这种情况下的更新甚至不会影响简单的POST表单...

通过失败上传发送的POST params请求是:

key: attachments/ad6d5c8c-f9ae-48ab-a9ff-c1b199a91d1d/File.txt

acl: public-read

policy: XXX==

signature: YYY=

Content-Type: binary/octet-stream

AWSAccessKeyId: -- Hidden --

......成功的一个:

key: attachments/368f5497-6e11-4f07-b379-80020e902013/File.txt

acl: public-read

policy: XXX==

signature: ZZZ=

Content-Type: binary/octet-stream

AWSAccessKeyId: -- Hidden --

似乎就像以前一样。唯一改变的属性是签名,因为路径中的随机guid生成...

以下是生成策略的其他一些方法:

def fields
    {
      key: key,
      acl: acl,
      policy: policy,
      signature: signature,
      "Content-Type" => content_type || "binary/octet-stream",
      "AWSAccessKeyId" => S3_CONFIG["access_key_id"]
    }
  end

  def policy
    Base64.encode64(policy_data.to_json).gsub("\n", "")
  end

  def policy_data
    {
      expiration: expiration,
      conditions: [
        {bucket: S3_CONFIG["bucket"]},
        ["starts-with", "$key", store_dir],
        {acl: acl},
        ["starts-with", "$Content-Type", ''],
        ["content-length-range", min_file_size, max_file_size]
      ]
    }
  end

  def signature
    Base64.encode64(
      OpenSSL::HMAC.digest(
        OpenSSL::Digest::Digest.new('sha1'),
        S3_CONFIG["secret_access_key"], policy
      )
    ).gsub("\n", "")
  end

我很欣赏任何帮助 感谢

2 个答案:

答案 0 :(得分:0)

让我试着总结一下。这只是草案的解决方案,因为我没有这里的环境来测试它。

•根据this,应使用url encode编码签名:

require 'open-uri'
signature = URI::encode(signature)

•政策/签名中的Gsubbing "\n"看起来有点可疑。我会尝试根本不触摸它,或者在.gsub("\n|\r")

的所有操作系统环境中删除所有可能的LF / CR

我会开始尝试使用编码而非gsubbed策略/签名,然后继续使用gsubbed版本。

希望它有所帮助。

答案 1 :(得分:0)

我遇到了同样的问题,但我通过打印解码“政策”来解决这个问题。在字段(表单)和签名中。

答案是策略方法被调用两次(在字段和签名中),每次生成的策略都有不同的到期值。这就是为什么它是随机的,并且每次都不会发生。

解决方案很简单 - 将策略保存在变量中以供以后访问:

  def policy
    @policy ||= Base64.encode64(policy_data.to_json).gsub("\n", "")
  end

固定的到期值也应该有效。