2010-10-18 3 views
2

Essayer de démarrer avec Amazon SNS. API est très simple REST. Je semble être accroché à la partie signature de l'appel. L'exemple de l'API est:Amazon SNS avec Python

http://sns.us-east-1.amazonaws.com/ 
?Subject=My%20first%20message 
&TopicArn=arn%3Aaws%3Asns%3Aus-east-1%3A698519295917%3AMy-Topic 
&Message=Hello%20world%21 
&Action=Publish 
&SignatureVersion=2 
&SignatureMethod=HmacSHA256 
&Timestamp=2010-03-31T12%3A00%3A00.000Z 
&AWSAccessKeyId=AKIAJHS4T6XPF7XIURNA 
&Signature=9GZysQ4Jpnz%2BHklqM7VFTvEcjR2LIUtn6jW47054xxE%3D 

Je suis cette API docs for signatures, donc je suis en train:

from time import strftime,gmtime,time 
import urllib2 
import hmac 
import hashlib 
import base64 
import string 

def publichSNSMsg(Subject,TopicArn,Message,AWSAccessKeyId,privatekey): 
    #http://docs.amazonwebservices.com/AWSSimpleQueueService/2008-01-01/SQSDeveloperGuide/ 
    amzsnshost = 'sns.us-east-1.amazonaws.com' 
    values = {'Subject' : Subject, 
      'TopicArn' : TopicArn, 
      'Message' :Message, 
      'Timestamp' : strftime("%Y-%m-%dT%H:%M:%S.000Z", gmtime(time())), 
      'AWSAccessKeyId' : AWSAccessKeyId, 
      'Action' : 'Publish', 
      'SignatureVersion' : '2', 
      'SignatureMethod' : 'HmacSHA256', 
      } 

    amazquote=lambda v: urllib2.quote(v).replace('%7E','~') 
    cannqs=string.join(["%s=%s"%(amazquote(key),amazquote(values[key])) for key in sorted(values.keys(),key=str.lower)],'&') 
    string_to_sign=string.join(["GET",amzsnshost,"/",cannqs],'\n') 

    sig=base64.encodestring(hmac.new(privatekey,string_to_sign,hashlib.sha1).digest()) 
    querystring = "%s&Signature=%s"%(cannqs,amazquote(sig)) 
    url="http://%s/?%s"%(amzsnshost,querystring) 

    try: 
    return urllib2.urlopen(url).read() 
    except urllib2.HTTPError, exception: 
    return "Error %s (%s):\n%s"%(exception.code,exception.msg,exception.read()) 

Et revenir:

<ErrorResponse xmlns="http://sns.amazonaws.com/doc/2010-03-31/"> 
    <Error> 
    <Type>Sender</Type> 
    <Code>SignatureDoesNotMatch</Code> 
    <Message>The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.</Message> 
    </Error> 
    <RequestId>8d6e5a41-dafb-11df-ac33-f981dc4e6c50</RequestId> 
</ErrorResponse> 

Toutes les idées?

Répondre

3

Oh, c'était simple!

Les clés de la chaîne de requête étaient supposées être octet-order triées, non sensibles à la casse triés (c'était pour les signatures de la version 1).

Un code légèrement mis à jour (et maintenant correct) est disponible sur gist.

+3

Il existe également une bibliothèque AWS python très complète appelée [boto] (http://github.com/boto/boto). –

1

J'ai trouvé cet exemple si utile que je l'ai réécrit en C#. Comme AWS n'a pas de bibliothèque WP7 pour SNS, peut-être que cela sera utile à quelqu'un: https://gist.github.com/2705156

1

Je vous suggère d'utiliser boto3 pour SNS. La documentation peut être trouvée au http://boto3.readthedocs.io/en/latest/reference/services/sns.html. L'extrait de code suivant peut être utilisé pour extraire la signature en tant que JSON.

import boto3 
from django.views.decorators.csrf import csrf_exempt 
topic_arn = <your topic> 
client = boto3.client('sns',region_name="us-west-2") 

#Call this to publish 
def sns_publish(arg1,arg2): 
    response = client.publish(
         TopicArn=topic_arn, 
         Message=arg2, 
         Subject=arg2 
        ) 

#Function to subscribe to topic 
@csrf_exempt 
def sns_parse(request): 
    print request.body.decode('utf-8') 
    if request.method == "POST": 
     response = json.loads(request.body.decode('utf-8')) 
     type = response.get('Type') 
     if type == 'Subscription': 
      print(type) 
      return("Subscription URL: "+<Url obtained>) 
     elif type == 'Notification': 
      return HttpResponse(type.get('Signature')) 
    else: 
     return HttpResponse('Not a POST object') 

Ceci est juste un code de modèle bien, mais oui, boto3 est en effet utile.