2009-07-06 82 views
2

我在我的Google應用程序引擎應用程序中使用Amazon web服務api。亞馬遜表示,他們將只接受2009年8月15日以前的簽名請求。雖然他們已經給出簡單的instructions進行簽名,但我並不熟悉SHA256的Python庫。應用引擎文檔says它支持pycrypto,但我只是想知道(讀懶)如果任何人已經這樣做。任何代碼片段,你可以分享?我可能在這裏錯過的任何問題?如何從Python應用引擎簽署亞馬遜網絡服務請求?

回答

2

根據代碼示例得到這個工作http://jjinux.blogspot.com/2009/06/python-amazon-product-advertising-api.html 這是一個小的改進版本,可以讓你在撥打電話之前合併一個特定於呼叫的參數字典和基本參數。

keyFile = open('accesskey.secret', 'r') 
# I put my secret key file in .gitignore so that it doesn't show up publicly 
AWS_SECRET_ACCESS_KEY = keyFile.read() 
keyFile.close() 

def amz_call(self, call_params): 

    AWS_ACCESS_KEY_ID = '<your-key>' 
    AWS_ASSOCIATE_TAG = '<your-tag>' 

    import time 
    import urllib 
    from boto.connection import AWSQueryConnection 
    aws_conn = AWSQueryConnection(
     aws_access_key_id=AWS_ACCESS_KEY_ID, 
     aws_secret_access_key=Amz.AWS_SECRET_ACCESS_KEY, is_secure=False, 
     host='ecs.amazonaws.com') 
    aws_conn.SignatureVersion = '2' 
    base_params = dict(
     Service='AWSECommerceService', 
     Version='2008-08-19', 
     SignatureVersion=aws_conn.SignatureVersion, 
     AWSAccessKeyId=AWS_ACCESS_KEY_ID, 
     AssociateTag=AWS_ASSOCIATE_TAG, 
     Timestamp=time.strftime("%Y-%m-%dT%H:%M:%S", time.gmtime())) 
    params = dict(base_params, **call_params) 
    verb = 'GET' 
    path = '/onca/xml' 
    qs, signature = aws_conn.get_signature(params, verb, path) 
    qs = path + '?' + qs + '&Signature=' + urllib.quote(signature) 
    print "verb:", verb, "qs:", qs 
    return aws_conn._mexe(verb, qs, None, headers={}) 

使用範例:

result = self.amz_call({'Operation' : 'ItemSearch' , 'Keywords' : searchString , 'SearchIndex' : 'Books' , 'ResponseGroup' : 'Small' }) 
if result.status == 200: 
    responseBodyText = result.read() 
    # do whatever ... 
+0

這對我不起作用 - 我得到「AttributeError:'AWSQueryConnection'對象沒有屬性'get_signature'」 – scubbo 2014-09-30 18:59:58

2

Pycrypto會正常工作 - 它在App Engine上支持,儘管公共密碼是用Python而不是C實現的。您還應該能夠使用現有的AWS庫之一,現在支持urlfetch/httplib App Engine。

我有一個將圖像上傳到S3的應用程序,我已經實現了自己的請求籤名,但主要是因爲我在urlfetch/httplib可用之前編寫了它。但它工作得很好。

+0

感謝您的回覆。我不明白使用現有AWS庫進行請求籤名的選項。有這樣的圖書館嗎?這不需要我發送我的密鑰嗎?當然,我在這裏錯過了一些東西。 – ottodidakt 2009-07-07 10:46:17

+0

所有的AWS庫都需要支持請求籤名,因爲它是我知道的訪問AWS的唯一方法。您需要將密鑰上傳到App Engine,但不需要將其發送到AWS。 Python的boto庫應該符合你的要求:http://code.google。com/p/boto/ – 2009-07-08 09:41:59

8

以下是基於較低級別(然後boto)庫的REST請求示例。解決方案取自http://cloudcarpenters.com/blog/amazon_products_api_request_signing

所有你需要的是AWS_ACCESS_KEY_ID有效條目,AWS_SECRET_ACCESS_KEY

def amazon_test_url(): 
    import base64, hashlib, hmac, time 
    from urllib import urlencode, quote_plus 

    AWS_ACCESS_KEY_ID = 'YOUR_KEY' 
    AWS_SECRET_ACCESS_KEY = 'YOUR_SECRET_KEY' 
    TEST_ISBN = '9780735619678' #http://stackoverflow.com/questions/1711/what-is-the-single-most-influential-book-every-programmer-should-read 

    base_url = "http://ecs.amazonaws.com/onca/xml" 
    url_params = dict(
     Service='AWSECommerceService', 
     Operation='ItemLookup', 
     IdType='ISBN', 
     ItemId=TEST_ISBN, 
     SearchIndex='Books', 
     AWSAccessKeyId=AWS_ACCESS_KEY_ID, 
     ResponseGroup='Images,ItemAttributes,EditorialReview,SalesRank') 

    #Can add Version='2009-01-06'. What is it BTW? API version? 


    # Add a ISO 8601 compliant timestamp (in GMT) 
    url_params['Timestamp'] = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()) 

    # Sort the URL parameters by key 
    keys = url_params.keys() 
    keys.sort() 
    # Get the values in the same order of the sorted keys 
    values = map(url_params.get, keys) 

    # Reconstruct the URL parameters and encode them 
    url_string = urlencode(zip(keys,values)) 

    #Construct the string to sign 
    string_to_sign = "GET\necs.amazonaws.com\n/onca/xml\n%s" % url_string 

    # Sign the request 
    signature = hmac.new(
     key=AWS_SECRET_ACCESS_KEY, 
     msg=string_to_sign, 
     digestmod=hashlib.sha256).digest() 

    # Base64 encode the signature 
    signature = base64.encodestring(signature).strip() 

    # Make the signature URL safe 
    urlencoded_signature = quote_plus(signature) 
    url_string += "&Signature=%s" % urlencoded_signature 

    print "%s?%s\n\n%s\n\n%s" % (base_url, url_string, urlencoded_signature, signature) 
0

我用這一個使用pycrypto生成自定義策略:

import json                                         
import time                                         

from Crypto.Hash import SHA                                     
from Crypto.PublicKey import RSA                                    
from Crypto.Signature import PKCS1_v1_5                                  
from base64 import b64encode                                     

url = "http://*"                                        
expires = int(time.time() + 3600) 

pem = """-----BEGIN RSA PRIVATE KEY----- 
... 
-----END RSA PRIVATE KEY-----""" 

key_pair_id = 'APK.....' 

policy = {}                                         
policy['Statement'] = [{}]                                     
policy['Statement'][0]['Resource'] = url                                  
policy['Statement'][0]['Condition'] = {}                                  
policy['Statement'][0]['Condition']['DateLessThan'] = {}                              
policy['Statement'][0]['Condition']['DateLessThan']['AWS:EpochTime'] = expires 

policy = json.dumps(policy) 

private_key = RSA.importKey(pem)                                    
policy_hash = SHA.new(policy)                                    
signer = PKCS1_v1_5.new(private_key)                                   
signature = b64encode(signer.sign(policy_hash)) 

print '?Policy=%s&Signature=%s&Key-Pair-Id=%s' % (b64encode(policy),                           
                signature,                             
                key_pair_id) 

這讓我使用了多個項目,像一個鍵:

http://your_domain/image1.png?Policy... 
http://your_domain/image2.png?Policy... 
http://your_domain/file1.json?Policy... 

不要忘記啓用pycrypto將此行添加到應用程序中.yaml

libraries: 
- name: pycrypto 
    version: latest