【发布时间】:2015-06-25 09:50:49
【问题描述】:
我正在使用下面的 ruby 代码生成一个表单(传递带有从 AWS 控制台下载的凭证作为参数的 CSV 文件)。如果我使用此表单提交文件,我会收到The request signature we calculated does not match the signature you provided. Check your key and signing method.。我已经从http://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html#signature-v4-examples-ruby 复制了签名代码。我看过Amazon MWS - request signature calculated does not match the signature provided 和s3 "signature doesn't match" client side post jquery-file-upload,但这些似乎不适用于我的情况。我哪里错了?
#!/usr/bin/env ruby
require 'nokogiri'
require 'csv'
require 'ostruct'
require 'base64'
require 'json'
require 'openssl'
header = nil
data = nil
CSV.foreach(ARGV[0]) do |row|
if header.nil?
header = row.collect{|c| c.strip.gsub(/\s/, '') }
else
data = row
end
end
creds = OpenStruct.new(Hash[*(header.zip(data).flatten)])
bucket = 'zotplus'
region = 'eu-central-1'
service = 's3'
dateStamp = Time.now.strftime('%Y%m%d')
policy = {
'expiration' => '2029-01-01T00:00:00Z',
'conditions' => [
{'bucket' => bucket},
['starts-with', '$key', 'uploads/'],
{'acl' => 'private'},
{'success_action_redirect' => 'http://zotplus.github.io/submitted.html'},
['starts-with', '$Content-Type', 'multipart/form-data'],
['content-length-range', 0, 1048576],
{'x-amz-date' => "#{dateStamp}T000000Z"},
{'x-amz-credential' => "#{creds.AccessKeyId}/#{dateStamp}/#{region}/#{service}/aws4_request"}
]
}
form = {}
%w{acl success_action_redirect bucket x-amz-date x-amz-credential}.each{|eq|
form[eq] = policy['conditions'].detect{|c| c.is_a?(Hash) && c[eq] }[eq]
}
form['key'] = policy['conditions'].detect{|c| c.is_a?(Array) && c[0,2] = ['starts-with', '$key']}[2] + '${filename}'
policy_string = Base64.encode64(policy.to_json).gsub("\n","")
kDate = OpenSSL::HMAC.digest('sha256', "AWS4" + creds.SecretAccessKey, dateStamp)
kRegion = OpenSSL::HMAC.digest('sha256', kDate, region)
kService = OpenSSL::HMAC.digest('sha256', kRegion, service)
kSigning = OpenSSL::HMAC.digest('sha256', kService, 'aws4_request')
signature = Base64.encode64(OpenSSL::HMAC.digest('sha256', kSigning, policy_string)).gsub("\n","")
form['policy'] = policy_string
form['x-amz-signature'] = signature
form['x-amz-algorithm'] = 'AWS4-HMAC-SHA256'
builder = Nokogiri::HTML::Builder.new do |doc|
doc.html {
doc.head {
doc.title {
doc.text 'submit file'
}
doc.meta('http-equiv' => "Content-Type", content: "text/html; charset=UTF-8")
}
doc.body {
doc.form(action: "http://zotplus-964ec2b7-379e-49a4-9c8a-edcb20db343f.s3.amazonaws.com/", method: "post", enctype: "multipart/form-data") {
form.each_pair{|k, v|
doc.input(type: "hidden", name: k, value: v)
}
doc.text 'File: '
doc.input(type: "file", name: "file")
doc.input(type: "submit", name: "submit", value: "Upload to Amazon S3")
}
}
}
end
puts builder.to_html
【问题讨论】:
-
获取一份S3 Signature V4 Test suite 的副本,看看你的表现如何。重要的是,测试套件包含您应该在中间步骤获得的结果(例如,规范请求和要签名的字符串),因此查找错误相对简单。如果没有,您至少可以将问题的焦点缩小到出现第一个不匹配的特定部分。
-
谢谢!这终于把我引向了问题所在。
标签: ruby amazon-web-services amazon-s3