1

在 GAE 上,我hmac用来为 AWS API 请求生成签名。我的代码原来是这样的:

import urllib
import urllib2
import time
import hmac
import base64
from hashlib import sha256 as sha256

class AmazonProductAdvertisingAPI:

    secret_access_key = '...'
    my_hmac = hmac.new(secret_access_key, digestmod=sha256)

    def get_signed_url(self, params):

        ....

        # Sign it
        self.my_hmac.update('GET' + "\n" + server + "\n" + path + "\n" + paramstring)
        urlstring = urlstring + "&Signature=" + \
            urllib.quote(base64.encodestring(self.my_hmac.digest()).strip())

        return urlstring

有了这个,我发现 API 请求(使用由 给出的 URL get_signed_url)当且仅当请求是实例的“冷启动”时,例如在我部署代码并第一次运行它之后。

但是,随后的请求失败了,AWS 声称签名无效。这是通过移至my_hmac方法内解决的,因此它是方法内的变量而不是类内的实例变量。

...
def get_signed_url(self, params):
    my_hmac = hmac.new(self.secret_access_key, digestmod=sha256)
    ...

我有一个问题:为什么?

4

1 回答 1

4

你的my_hmac变量是一个类变量;一个由类的所有实例共享。

这意味着每次调用都会.get_signed_url()将数据添加到摘要中,跨实例,全局到应用程序。self.my_hmac.update()

由于您只想计算一个字符串("GET ..."字符串)的摘要,而不是累积计算所有字符串的摘要,因此您必须hmac为要计算的每个新摘要创建一个新对象。

请注意.update()` 方法的文档

使用字符串 arg 更新哈希对象。重复调用等效于连接所有参数的单个调用:m.update(a); m.update(b)等效于m.update(a+b).

于 2013-02-10T00:19:17.430 回答