2013-02-10 88 views
1

在GAE上,我使用hmac爲AWS API請求生成簽名。我的代碼最初是這樣的:GAE - 奇怪的實例變量行爲

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) 
    ... 

我有一個問題:爲什麼?

回答

4

您的my_hmac變量是一個類變量;一個由共享的全部類實例。

這意味着每次調用.get_signed_url()self.my_hmac.update()調用將數據添加到消化,跨實例,在全球範圍內應用。

由於您只想計算摘要只有一個字符串,(在"GET ..."字符串),而不是對所有字符串日積月累,你必須創建爲每個新新hmac對象消化要計算。

注意documentation for the .update()` method

更新與字符串ARG哈希對象。重複調用相當於所有參數連接的單個調用:​​相當於m.update(a+b)

+0

Doh!第一次使用Python。 – 2013-02-10 00:20:37

+0

所以,這是一個類變量。我如何創建實例變量?在__init__內? – 2013-02-10 00:22:08

+1

在'__init__'中,是的。分配給'self.someattribute'的方法內的任何內容都是設置實例變量。 – 2013-02-10 00:22:20