我正在尝试使用Python对亚马逊的SimpleDB服务进行API调用。举个例子,我用的是最简单的请求,ListDomains
。然而,无论我如何尝试,响应总是"我们计算的请求签名与您提供的签名不匹配"。
这是我正在签名的字符串(按照这里的文档):
GET
https://sdb.amazonaws.com/
/
AWSAccessKeyId=<redacted>&Action=ListDomains&SignatureMethod=HmacSHA1&SignatureVersion=2&Timestamp=2011-04-19T18%3A50%3A43&Version=2009-04-15
我用下面的代码签名:
import base64,hashlib,hmac,time
# Sign the request
signature = hmac.new(
key=AWS_SECRET_ACCESS_KEY,
msg=string_to_sign,
digestmod=hashlib.sha1).digest()
# Base64 encode the signature
signature = base64.encodestring( signature )
我已经尝试过HmacSHA256和HmacSHA1。似乎什么都不管用。我做错了什么?
一个关键问题是你必须正确地对所有HTTP参数值进行URL编码。
下面的文档已经从SimpleDB文档中消失了,但是可以在SQS文档中找到,并且仍然与SimpleDB非常相关:
不要对任何URL进行编码rfc3986规定的非保留字符定义。
这些无保留字符是A-Z,A-z, 0-9,连字符-,下划线_),句号(。),和波浪(~)。
%编码所有其他字符与%XY,其中X和Y是十六进制字符0-9和大写字母A-F.
%编码扩展UTF-8格式为%XY%ZA
的字符%将空格字符编码为%20(而不是+,作为通用编码)计划做)。
您将注意到,在Roger链接的python-simpledb
模块中,它们在形成请求时遵循以下规则:
def escape(s):
return urllib.quote(s, safe='-_~')
def urlencode(d):
if isinstance(d, dict):
d = d.iteritems()
return '&'.join(['%s=%s' % (escape(k), escape(v)) for k, v in d])
我不想重新发明轮子-有几个python simpledb库,如;
- https://github.com/sixapart/python-simpledb
- http://code.google.com/p/boto/wiki/SimpleDbIntro
如果没有别的,他们的签名代码应该澄清你的错误是什么,但说真的,使用现有的维护API,它会让你的生活更容易。