向AWS S3提交POST时签名不匹配错误
这是我的表单
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<form action="http://mybucket.s3.amazonaws.com/" method="post" enctype="multipart/form-data">
Key to upload: <input type="input" name="key" value="user/eric/" /><br />
<input type="hidden" name="acl" value="public-read" />
<input type="hidden" name="AWSAccessKeyId" value="myAWSId" />
<input type="hidden" name="Policy" value="Base64EncodingOfPolicy"/>
<input type="hidden" name="Signature" value="Signature Calculated as urlencode(base64(HMAC-SHA1(secret, policy base64 encoded string same as utf-8 encoded)))" />
File: <input type="file" name="file" /> <br />
<!-- The elements after this will be ignored -->
<input type="submit" name="submit" value="Upload to Amazon S3" />
</form>
</html>
这是我的政策
{ "expiration": "2014-12-01T12:00:00.000Z",
"conditions": [
{"acl": "public-read" },
{"bucket": "mybucket" },
["starts-with", "$key", "user/eric/"],
]
}
这是经过base64编码的政策
eyAiZXhwaXJhdGlvbiI6ICIyMDE0LTEyLTAxVDEyOjAwOjAwLjAwMFoiLA0KDQogICJjb25kaXRp
b25zIjogWw0KDQogICAgeyJhY2wiOiAicHVibGljLXJlYWQiIH0sDQoNCiAgICB7ImJ1Y2tldCI6
ICJoYWJpdHN1c2VybWVkaWEiIH0sDQoNCiAgICBbInN0YXJ0cy13aXRoIiwgIiRrZXkiLCAidXNl
ci9lcmljLyJdLA0KDQogIF0NCg0KfQ==
我尝试过使用带有和不带有换行符的base64编码字符串。在使用上述编码和换行符时,我应该注意什么特别的地方吗?
即使经过多次尝试,我仍然收到SignatureDoesNotMatch
的错误,感觉我已经考虑了所有可能的组合。
我还使用了签名验证工具,检查了AWS接受的内容,结果是匹配的。http://aws.amazon.com/code/199
我该如何调试这个问题?如果你成功使用REST API向S3发送过POST请求,能分享一下代码片段吗?
1 个回答
2
好的,我花了一段时间终于解决了这个问题。
这是我用Python写的代码,用来生成签名
import base64
import hmac
from hashlib import sha1
import urllib
input = open("policy.txt", "rb")
policy = input.read()
policy_encoded = base64.b64encode(policy).encode("UTF-8")
secret = "<my_aws_secret>"
print 'Encoded Policy %s' %(policy_encoded)
hashed = hmac.new(secret,policy_encoded, sha1)
#This is the required value
signature = base64.b64encode(hashed.digest())
#This is not required for a HTTP POST form based request, only when it has to be passed in urlencoded format
signature_urlencoded = urllib.quote_plus(base64.b64encode(hashed.digest()))
print 'Signature urlencoded %s' %(signature)
我的policy.txt文件内容是
{ "expiration": "2014-12-01T12:00:00.000Z",
"conditions": [
{"acl": "public-read" },
{"bucket": "<mybucket>" },
{"success_action_status" : "201"},
["starts-with", "$key", "uploads/"],
]
}
而我的表单看起来是这样的
<form action="http://habitsusermedia.s3.amazonaws.com/" method="post" enctype="multipart/form-data">
<input type="hidden" name="acl" value="public-read" />
<input type="input" name="key" value="uploads/${filename}" />
<input type="hidden" name="success_action_status" value="201" />
<input type="hidden" name="AWSAccessKeyId" value="<aws_access_key>" />
<input type="hidden" name="Policy" value="<policy_encoded_as_base64>"/>
<input type="hidden" name="Signature" value="<signature>" />
File: <input type="file" name="file" /> <br />
<!-- The elements after this will be ignored -->
<input type="submit" name="submit" value="Upload to Amazon S3" />
</form>
确保你的AWS存储桶设置为接受来自任何域的POST和PUT请求。可以使用政策生成工具来做到这一点。
有一篇很有帮助的文章解释了这些概念,链接在这里:AWS