Signieren einer Amazon-Webdienstanforderung in .NET mit SOAP und ohne WSE

Die Amazon Product Advertising API (ehemals Amazon Associates Web Service oder Amazon AWS) hat eine neue Regel implementiert, nach der bis zum 15. August 2009 alle an sie gerichteten Webservice-Anfragen signiert werden müssen. Sie haben auf ihrer Site Beispielcode bereitgestellt, der zeigt, wie dies in C # sowohl mit REST als auch mit SOAP durchgeführt wird. Die Implementierung, die ich verwende, ist SOAP. Sie finden den BeispielcodeHierIch beziehe es nicht mit ein, weil es einen angemessenen Betrag gibt.

Das Problem, das ich habe, ist, dass der Beispielcode WSE 3 verwendet und unser aktueller Code WSE nicht verwendet. Weiß jemand, wie man dieses Update nur mit dem automatisch generierten Code aus der WSDL implementiert? Ich möchte jetzt nicht auf das WSE 3 - Zeug umsteigen müssen, wenn ich nicht muss, da dieses Update eher ein schneller Patch ist, der uns zurückhält, bis wir dies in der aktuellen Dev - Version (August) vollständig implementieren können 3. Sie beginnen, 1 in 5 Anfragen in der Live-Umgebung zu senden, wenn sie nicht signiert sind (was für unsere Anwendung eine schlechte Nachricht ist).

Hier ist ein Ausschnitt aus dem Hauptteil, der die eigentliche Signatur der SOAP-Anfrage ausführt.

class ClientOutputFilter : SoapFilter
{
    // to store the AWS Access Key ID and corresponding Secret Key.
    String akid;
    String secret;

    // Constructor
    public ClientOutputFilter(String awsAccessKeyId, String awsSecretKey)
    {
        this.akid = awsAccessKeyId;
        this.secret = awsSecretKey;
    }

    // Here's the core logic:
    // 1. Concatenate operation name and timestamp to get StringToSign.
    // 2. Compute HMAC on StringToSign with Secret Key to get Signature.
    // 3. Add AWSAccessKeyId, Timestamp and Signature elements to the header.
    public override SoapFilterResult ProcessMessage(SoapEnvelope envelope)
    {
        var body = envelope.Body;
        var firstNode = body.ChildNodes.Item(0);
        String operation = firstNode.Name;

        DateTime currentTime = DateTime.UtcNow;
        String timestamp = currentTime.ToString("yyyy-MM-ddTHH:mm:ssZ");

        String toSign = operation + timestamp;
        byte[] toSignBytes = Encoding.UTF8.GetBytes(toSign);
        byte[] secretBytes = Encoding.UTF8.GetBytes(secret);
        HMAC signer = new HMACSHA256(secretBytes);  // important! has to be HMAC-SHA-256, SHA-1 will not work.

        byte[] sigBytes = signer.ComputeHash(toSignBytes);
        String signature = Convert.ToBase64String(sigBytes); // important! has to be Base64 encoded

        var header = envelope.Header;
        XmlDocument doc = header.OwnerDocument;

        // create the elements - Namespace and Prefix are critical!
        XmlElement akidElement = doc.CreateElement(
            AmazonHmacAssertion.AWS_PFX, 
            "AWSAccessKeyId", 
            AmazonHmacAssertion.AWS_NS);
        akidElement.AppendChild(doc.CreateTextNode(akid));

        XmlElement tsElement = doc.CreateElement(
            AmazonHmacAssertion.AWS_PFX,
            "Timestamp",
            AmazonHmacAssertion.AWS_NS);
        tsElement.AppendChild(doc.CreateTextNode(timestamp));

        XmlElement sigElement = doc.CreateElement(
            AmazonHmacAssertion.AWS_PFX,
            "Signature",
            AmazonHmacAssertion.AWS_NS);
        sigElement.AppendChild(doc.CreateTextNode(signature));

        header.AppendChild(akidElement);
        header.AppendChild(tsElement);
        header.AppendChild(sigElement);

        // we're done
        return SoapFilterResult.Continue;
    }
}

Und das wird so aufgerufen, wenn der eigentliche Webservice aufgerufen wird

// create an instance of the serivce
var api = new AWSECommerceService();

// apply the security policy, which will add the require security elements to the
// outgoing SOAP header
var amazonHmacAssertion = new AmazonHmacAssertion(MY_AWS_ID, MY_AWS_SECRET);
api.SetPolicy(amazonHmacAssertion.Policy());

Antworten auf die Frage(4)

Ihre Antwort auf die Frage