GAE - 奇怪的实例变量行为

时间:2013-02-10 00:10:49

标签: python google-app-engine

在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请求(使用get_signed_url给出的URL)当且仅当请求是实例的“冷启动”时,例如在我部署代码并且第一次运行它之后。

但是,后续请求失败,AWS声称签名无效。这是通过将my_hmac移动到方法中来解决的,因此它是方法中的变量而不是类中的实例变量。

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

我有一个问题:为什么?

1 个答案:

答案 0 :(得分:4)

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

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

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

请注意documentation for the .update()` method

  

使用字符串arg更新哈希对象。重复调用相当于单个调用,并且所有参数都连接在一起:m.update(a); m.update(b)等同于m.update(a+b)