[英]AWS authentication V4 signature failure; where am I going wrong in generating the signature?
我正在使用下面的Ruby代碼生成表單(將帶有從AWS控制台下載的憑證的CSV文件作為參數傳遞給CSV文件)。 如果我使用此表單提交文件, The request signature we calculated does not match the signature you provided. Check your key and signing method.
得到The request signature we calculated does not match the signature you provided. Check your key and signing method.
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-計算的請求簽名與提供的簽名不匹配,並且s3“簽名不匹配”客戶端發布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
好的,事實證明策略簽名不應該使用base64編碼,而只能以十六進制摘要形式輸出。 對於那些同樣遇到難題的人,最終的結果是:
#!/usr/bin/env ruby
require 'json'
require 'base64'
require 'openssl'
require 'csv'
require 'ostruct'
require 'nokogiri'
algorithm = 'AWS4-HMAC-SHA256'
service = 's3'
requestType = 'aws4_request'
successStatus = '201'
bucket = 'zotplus-964ec2b7-379e-49a4-9c8a-edcb20db343f'
region = 'eu-central-1'
acl = 'private'
header = nil
data = nil
CSV.foreach(ENV['ZOTPLUSAWSCREDENTIALS']) 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)])
date = Time.now.strftime('%Y%m%dT%H%M%SZ')
shortDate = date.sub(/T.*/, '')
credentials = [ creds.AccessKeyId, shortDate, region, service, requestType ].join('/')
policy = Base64.encode64({
'expiration' => (Time.now + (60*60*24*365*30)).strftime('%Y-%m-%dT%H:%M:%SZ'), # 30 years from now
'conditions' => [
{'bucket' => bucket},
{'acl' => acl},
['starts-with', '$key', ''],
['starts-with', '$Content-Type', ''],
{'success_action_status' => successStatus},
{'x-amz-credential' => credentials},
{'x-amz-algorithm' => algorithm},
{'x-amz-date' => date},
['content-length-range', 0, 1048576],
]
}.to_json).gsub("\n","")
signingKey = ['AWS4' + creds.SecretAccessKey, shortDate, region, service, requestType].inject{|key, data| OpenSSL::HMAC.digest('sha256', key, data) }
form = OpenStruct.new({
action: "http://#{bucket}.#{service}-#{region}.amazonaws.com",
fields: [ # order matters!
{key: '${filename}'},
{'Content-Type': 'text/plain'},
{acl: acl},
{success_action_status: successStatus},
{policy: policy},
{'x-amz-algorithm': algorithm},
{'x-amz-credential': credentials},
{'x-amz-date': date},
{'x-amz-signature': OpenSSL::HMAC.hexdigest('sha256', signingKey, policy)}
]
})
################################################
builder = Nokogiri::HTML::Builder.new do |doc|
doc.html {
doc.head {
doc.meta(charset: 'utf-8')
doc.title { doc.text 'Upload' }
}
doc.body {
doc.form(action: form.action, method: 'POST', enctype: "multipart/form-data") {
form.fields.each{|field|
field.each_pair{|name, value|
doc.input(type: 'hidden', name: name, value: value)
}
}
doc.input(type: 'file', name: 'file')
doc.input(type: 'submit', value: 'Save')
}
}
}
end
puts builder.to_html
是的,它是有效的:DI這樣嘗試過
def index
access_key = 'YOUR_ACCESS_KEY'
secret_key = 'YOUR_SECRET_KEY'
time = Time.now.utc
date_stamp = time.strftime("%Y%m%d")
region_name = 'ap-south-1'
key_date = hmac_digest('sha256', "AWS4" + secret_key, date_stamp)
key_region = hmac_digest('sha256', key_date, region_name)
key_service = hmac_digest('sha256', key_region, 's3')
key_signing = hmac_digest('sha256', key_service, "aws4_request")
algorithm = 'AWS4-HMAC-SHA256'
amzdate = time.strftime('%Y%m%dT%H%M%SZ')
credential_scope = access_key + '/' + date_stamp + '/ap-south-1/s3/aws4_request'
policy = generate_policy(credential_scope, algorithm, amzdate)
signature = OpenSSL::HMAC.hexdigest('sha256', key_signing, policy)
render json: { policy: policy, signature: signature, key: access_key, date: amzdate, credentials: credential_scope, algorithm: algorithm }
end
def generate_policy(credential_scope, algorithm, amzdate)
Base64.encode64({
'expiration' => (Time.now + (60 * 60 * 24 * 365 * 30)).strftime('%Y-%m-%dT%H:%M:%SZ'), # 30 years from now
'conditions' => [
{ 'bucket' => 'adcreation-m' },
{ 'acl' => 'public-read' },
['starts-with', '$key', ''],
['starts-with', '$Content-Type', ''],
{ 'success_action_status' => '201' },
{ 'x-amz-credential' => credential_scope },
{ 'x-amz-algorithm' => algorithm },
{ 'x-amz-date' => amzdate },
['content-length-range', 0, 256000000]
]
}.to_json).delete("\n")
end
def hmac_digest(digest, key, data)
OpenSSL::HMAC.digest(digest, key, data)
end
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.