Aufrufen von REST-API-Vorgängen mit Autorisierung mit gemeinsam verwendetem Schlüssel

In diesem Artikel erfahren Sie, wie Sie einen REST-API-Vorgang für Azure Storage aufrufen, indem Sie eine autorisierte REST-Anforderung mit C# erstellen. Nachdem Sie gelernt haben, wie Sie einen REST-API-Vorgang für Blob Storage aufrufen, können Sie ähnliche Schritte für alle anderen REST-Vorgänge für Azure Storage ausführen.

Voraussetzungen

Die Beispielanwendung listet die Blobcontainer für ein Speicherkonto auf. Sie benötigen Folgendes, um den Code in diesem Artikel ausprobieren zu können:

  • Installieren Sie Visual Studio mit der Workload Azure-Entwicklung. Dieses Beispiel wurde mit Visual Studio 2019 erstellt. Wenn Sie eine andere Version verwenden, kann die Anleitung geringfügig variieren.

  • Ein Azure-Abonnement. Wenn Sie kein Azure-Abonnement besitzen, können Sie ein kostenloses Konto erstellen, bevor Sie beginnen.

  • Ein allgemeines Speicherkonto. Falls Sie noch kein Speicherkonto haben, lesen Sie Erstellen eines Speicherkontos.

  • Mit dem Beispiel in diesem Artikel wird veranschaulicht, wie Sie die Container in einem Speicherkonto auflisten. Fügen Sie dem Speicherkonto zunächst einige Container hinzu, um eine Ausgabe zu erhalten.

Herunterladen der Beispielanwendung

Die Beispielanwendung ist eine Konsolenanwendung in C#.

Verwenden Sie Git, um eine Kopie der Anwendung in Ihre Entwicklungsumgebung herunterzuladen.

git clone https://github.com/Azure-Samples/storage-dotnet-rest-api-with-auth.git

Mit diesem Befehl wird das Repository in Ihren lokalen Git-Ordner geklont. Navigieren Sie zum Öffnen der Visual Studio-Projektmappe zum Ordner „storage-dotnet-rest-api-with-auth“, und öffnen Sie „StorageRestApiAuth.sln“.

Informationen zu REST

REST (Representational State Transfer) ist eine Architektur, die es Ihnen ermöglicht, mit einem Dienst über ein Internetprotokoll wie HTTP/HTTPS zu interagieren. REST ist unabhängig von der Software, die auf dem Server oder dem Client ausgeführt wird. Die REST-API kann von jeder Plattform aufgerufen werden, die HTTP/HTTPS unterstützt. Sie können eine Anwendung schreiben, die auf einem Mac-, Windows- oder Linux-Computer, Android-Smartphone oder -Tablet, iPhone, iPod oder einer Website ausgeführt wird, und für alle Plattformen die gleiche REST-API verwenden.

Ein Aufruf der REST-API besteht aus einer Anforderung des Clients und einer zurückgegebenen Antwort des Diensts. In der Anforderung senden Sie eine URL mit Informationen darüber, welchen Vorgang Sie aufrufen möchten, die zu berücksichtigende Ressource, alle Abfrageparameter und Header sowie je nach abgerufenem Vorgang eine Nutzlast von Daten. Die Antwort des Dienstes umfasst einen Statuscode, einen Satz von Antwortheadern und je nach aufrufendem Vorgang eine Nutzlast von Daten.

Infos zur Beispielanwendung

Die Beispielanwendung listet die Container in einem Speicherkonto auf. Wenn Sie verstanden haben, wie die Informationen in der REST-API-Dokumentation mit Ihrem tatsächlichen Code korrelieren, sind andere REST-Aufrufe einfacher nachzuvollziehen.

Wenn Sie sich die Blob-Dienst-REST-API ansehen, werden alle Vorgänge angezeigt, die Sie für Blobspeicher durchführen können. Die Speicherclientbibliotheken dienen als Wrapper für die REST-APIs. Sie erleichtern den Zugriff auf Speicherressourcen ohne direkte Verwendung der REST-APIs. Manchmal möchten Sie jedoch vielleicht anstelle einer Speicherclientbibliothek die REST-API nutzen.

Vorgang zum Auflisten von Containern

Dieser Artikel konzentriert sich auf den Vorgang List Containers. Die folgenden Informationen helfen Ihnen dabei, einige der Felder in der Anforderung und Antwort besser zu verstehen.

Anforderungsmethode: GET. Dieses Verb ist die HTTP-Methode, die Sie als Eigenschaft des Anforderungsobjekts angeben. Andere Werte für dieses Verb sind HEAD, PUT und DELETE (je nach aufgerufener API).

Anforderungs-URI: https://myaccount.blob.core.windows.net/?comp=list. Der Anforderungs-URI wird aus dem Blob Storage-Kontoendpunkt https://myaccount.blob.core.windows.net und der Ressourcenzeichenfolge /?comp=list erstellt.

URI-Parameter: Es sind zusätzliche Abfrageparameter vorhanden, die Sie beim Aufrufen von ListContainers verwenden können. Zwei dieser Parameter sind timeout für den Aufruf (in Sekunden) und prefix für die Filterung.

Ein weiterer hilfreicher Parameter ist maxresults:. Wenn mehr Container als unter diesem Wert angegeben verfügbar sind, enthält der Antworttext ein NextMarker-Element, mit dem der nächste Container angegeben wird, der bei der nächsten Anforderung zurückgegeben wird. Zur Verwendung dieses Features geben Sie den Wert von NextMarker als Parameter marker im URI an, wenn Sie die nächste Anforderung senden. Bei Verwendung dieses Features entspricht dies dem Blättern durch die Ergebnisse.

Falls Sie zusätzliche Parameter verwenden möchten, können Sie sie an die Ressourcenzeichenfolge mit dem Wert anfügen. Beispiel:

/?comp=list&timeout=60&maxresults=100

Anforderungsheader: In diesem Abschnitt sind die erforderlichen und optionalen Anforderungsheader aufgeführt. Drei Header sind erforderlich: ein Authorization-Header, x-ms-date (enthält die UTC-Zeit für die Anforderung) und x-ms-version (gibt die Version der zu verwendenden REST-API an). x-ms-client-request-id kann optional in die Header eingeschlossen werden. Sie können den Wert für dieses Feld beliebig festlegen. Er wird in die Speicheranalyseprotokolle geschrieben, wenn die Protokollierung aktiviert ist.

Anforderungstext: Für „ListContainers“ ist kein Anforderungstext vorhanden. Der Anforderungstext wird für alle PUT-Vorgänge verwendet, wenn Blobs hochgeladen werden (einschließlich „SetContainerAccessPolicy“). Mit dem Anforderungstext können Sie eine XML-Liste mit gespeicherten Zugriffsrichtlinien senden, die angewendet werden sollen. Gespeicherte Zugriffsrichtlinien werden im Artikel Verwenden von Shared Access Signatures (SAS) beschrieben.

Antwortstatuscode: Enthält Informationen zu allen Statuscodes, die Sie kennen müssen. In diesem Beispiel bedeutet der HTTP-Statuscode 200, dass alles in Ordnung ist. Eine vollständige Liste mit HTTP-Statuscodes finden Sie unter Status Code Definitions (Statuscodedefinitionen). Informationen zu spezifischen Fehlercodes der Storage-REST-APIs finden Sie unter Bekannte REST API-Fehlercodes.

Antwortheader: Hierzu gehören Content Type, x-ms-request-id (die übergebene Anforderungs-ID), x-ms-version (gibt die Version des verwendeten Blob-Diensts an) und Date (UTC-Zeitpunkt der Anforderung).

Antworttext: Dieses Feld ist eine XML-Struktur, über die die angeforderten Daten bereitgestellt werden. In diesem Beispiel umfasst die Antwort eine Liste mit Containern und ihren Eigenschaften.

Erstellen der REST-Anforderung

Verwenden Sie bei der Ausführung in der Produktion aus Sicherheitsgründen nicht HTTP, sondern immer HTTPS. In dieser Übung wird HTTP verwendet, damit Sie sich die Anforderungs- und Antwortdaten ansehen können. Zum Anzeigen der Anforderungs- und Antwortinformationen in den eigentlichen REST-Aufrufen können Sie Fiddler oder eine ähnliche Anwendung herunterladen. In der Visual Studio-Projektmappe sind der Name und der Schlüssel des Speicherkontos in der Klasse hartcodiert. Die ListContainersAsyncREST-Methode übergibt den Speicherkontonamen und -schlüssel an die Methoden, die zum Erstellen der verschiedenen Komponenten einer REST-Anforderung verwendet werden. In einer echten Anwendung befinden sich der Speicherkontoname und -schlüssel in einer Konfigurationsdatei oder in Umgebungsvariablen oder werden aus einem Azure Key Vault abgerufen.

In unserem Beispielprojekt befindet sich der Code zum Erstellen des Autorisierungsheaders in einer separaten Klasse. Die Idee ist, dass Sie die gesamte Klasse übernehmen, sie Ihrer eigenen Lösung hinzufügen und „wie gehabt“ verwenden können. Der Headercode für die Autorisierung funktioniert für die meisten REST-API-Aufrufe Azure Storage.

Navigieren Sie zum Erstellen der Anforderung, bei der es sich um ein HttpRequestMessage-Objekt handelt, zu „ListContainersAsyncREST“ in „Program.cs“. Die Schritte zum Erstellen der Anforderung sind:

  • Erstellen Sie den URI, der zum Aufrufen des Diensts verwendet werden soll.
  • Erstellen Sie das HttpRequestMessage-Objekt, und legen Sie die Nutzlast fest. Die Nutzlast ist für ListContainersAsyncREST null, weil wir nichts übergeben.
  • Fügen Sie die Anforderungsheader für „x-ms-date“ und „x-ms-version“ hinzu.
  • Rufen Sie den Autorisierungsheader ab, und fügen Sie ihn hinzu.

Sie benötigen diese grundlegenden Informationen:

  • Für ListContainers wird GET als method (Methode) verwendet. Dieser Wert wird beim Instanziieren der Anforderung festgelegt.
  • Die resource (Ressource) ist der Abfrageteil des URI, mit dem angegeben wird, welche API aufgerufen wird. Der Wert lautet /?comp=list. Wie bereits erwähnt, befindet sich die Ressource auf der Seite der Referenzdokumentation, die die Informationen zur ListContainers-API enthält.
  • Der URI wird erstellt, indem der Blob-Dienst-Endpunkt für dieses Speicherkonto erstellt und die Ressource verkettet wird. Der Wert für request URI (Anforderungs-URI) ist dann http://contosorest.blob.core.windows.net/?comp=list.
  • Für ListContainers ist requestBody null, und es sind keine zusätzlichen Header vorhanden.

Bei anderen APIs müssen möglicherweise andere Parameter übergeben werden (z. B. ifMatch). Ein Beispiel für die Verwendung von ifMatch ist das Aufrufen von PutBlob. In diesem Fall legen Sie ifMatch auf ein ETag fest. Das Blob wird dann nur aktualisiert, wenn das von Ihnen angegebene ETag mit dem aktuellen ETag des Blobs übereinstimmt. Wenn eine andere Person das Blob seit dem Abruf des ETags aktualisiert hat, wird deren Änderung nicht überschrieben.

Legen Sie zuerst uri und requestPayload fest.

// Construct the URI. It will look like this:
//   https://myaccount.blob.core.windows.net/resource
String uri = string.Format("http://{0}.blob.core.windows.net?comp=list", storageAccountName);

// Provide the appropriate payload, in this case null.
//   we're not passing anything in.
Byte[] requestPayload = null;

Instanziieren Sie als Nächstes die Anforderung, indem Sie die Methode auf GET festlegen und den URI angeben.

// Instantiate the request message with a null payload.
using (var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, uri)
{ Content = (requestPayload == null) ? null : new ByteArrayContent(requestPayload) })
{

Fügen Sie die Anforderungsheader für x-ms-date und x-ms-version hinzu. An dieser Stelle im Code fügen Sie auch alle zusätzlichen Anforderungsheader hinzu, die für den Aufruf erforderlich sind. In diesem Beispiel sind keine zusätzlichen Header vorhanden. Ein Beispiel für eine API, von der zusätzliche Header übergeben werden, ist der Vorgang „Set Container ACL“ (Festlegen der Container-ACL). Dieser API-Aufruf fügt einen Header mit dem Namen „x-ms-blob-public-access“ und der Wert für die Zugriffsebene hinzu.

// Add the request headers for x-ms-date and x-ms-version.
DateTime now = DateTime.UtcNow;
httpRequestMessage.Headers.Add("x-ms-date", now.ToString("R", CultureInfo.InvariantCulture));
httpRequestMessage.Headers.Add("x-ms-version", "2017-07-29");
// If you need any additional headers, add them here before creating
//   the authorization header.

Rufen Sie die Methode auf, mit der der Autorisierungsheader erstellt wird, und fügen Sie sie den Anforderungsheadern hinzu. Der Autorisierungsheader wird später in diesem Artikel erstellt. Der Methodenname lautet GetAuthorizationHeader, der in diesem Codeausschnitt zu sehen ist:

// Get the authorization header and add it.
httpRequestMessage.Headers.Authorization = AzureStorageAuthenticationHelper.GetAuthorizationHeader(
    storageAccountName, storageAccountKey, now, httpRequestMessage);

An diesem Punkt enthält httpRequestMessage die vollständige REST-Anforderung mit den Autorisierungsheadern.

Senden der Anforderung

Nachdem Sie die Anforderung erstellt haben, können Sie die SendAsync-Methode aufrufen, um sie an Azure Storage zu senden. Wenn der Statuscode 200 zurückgegeben wird, war der Vorgang erfolgreich. Analysieren Sie als Nächstes die Antwort. In diesem Fall erhalten Sie eine XML-Liste mit Containern. Wir sehen uns nun den Code zum Aufrufen der GetRESTRequest-Methode für das Erstellen der Anforderung, Ausführen der Anforderung und anschließende Prüfen der Antwort auf die Liste mit den Containern an.

    // Send the request.
    using (HttpResponseMessage httpResponseMessage =
      await new HttpClient().SendAsync(httpRequestMessage, cancellationToken))
    {
        // If successful (status code = 200),
        //   parse the XML response for the container names.
        if (httpResponseMessage.StatusCode == HttpStatusCode.OK)
        {
            String xmlString = await httpResponseMessage.Content.ReadAsStringAsync();
            XElement x = XElement.Parse(xmlString);
            foreach (XElement container in x.Element("Containers").Elements("Container"))
            {
                Console.WriteLine("Container name = {0}", container.Element("Name").Value);
            }
        }
    }
}

Wenn Sie beim Aufrufen von SendAsync beispielsweise einen Network Sniffer wie Fiddler ausführen, können Sie die Informationen zur Anforderung und zur Antwort anzeigen. Wir sehen uns dies nun genauer an. Der Name des Speicherkontos lautet contosorest.

Anforderung:

GET /?comp=list HTTP/1.1

Anforderungsheader:

x-ms-date: Thu, 16 Nov 2017 23:34:04 GMT
x-ms-version: 2014-02-14
Authorization: SharedKey contosorest:1dVlYJWWJAOSHTCPGiwdX1rOS8B4fenYP/VrU0LfzQk=
Host: contosorest.blob.core.windows.net
Connection: Keep-Alive

Nach der Ausführung zurückgegebener Statuscode bzw. Antwortheader:

HTTP/1.1 200 OK
Content-Type: application/xml
Server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: 3e889876-001e-0039-6a3a-5f4396000000
x-ms-version: 2017-07-29
Date: Fri, 17 Nov 2017 00:23:42 GMT
Content-Length: 1511

Antworttext (XML): Für den Vorgang „Container auflisten“ wird hier die Liste der Container mit den zugehörigen Eigenschaften angezeigt.

<?xml version="1.0" encoding="utf-8"?>
<EnumerationResults
  ServiceEndpoint="http://contosorest.blob.core.windows.net/">
  <Containers>
    <Container>
      <Name>container-1</Name>
      <Properties>
        <Last-Modified>Thu, 16 Mar 2017 22:39:48 GMT</Last-Modified>
        <Etag>"0x8D46CBD5A7C301D"</Etag>
        <LeaseStatus>unlocked</LeaseStatus>
        <LeaseState>available</LeaseState>
      </Properties>
    </Container>
    <Container>
      <Name>container-2</Name>
      <Properties>
        <Last-Modified>Thu, 16 Mar 2017 22:40:50 GMT</Last-Modified>
        <Etag>"0x8D46CBD7F49E9BD"</Etag>
        <LeaseStatus>unlocked</LeaseStatus>
        <LeaseState>available</LeaseState>
      </Properties>
    </Container>
    <Container>
      <Name>container-3</Name>
      <Properties>
        <Last-Modified>Thu, 16 Mar 2017 22:41:10 GMT</Last-Modified>
        <Etag>"0x8D46CBD8B243D68"</Etag>
        <LeaseStatus>unlocked</LeaseStatus>
        <LeaseState>available</LeaseState>
      </Properties>
    </Container>
    <Container>
      <Name>container-4</Name>
      <Properties>
        <Last-Modified>Thu, 16 Mar 2017 22:41:25 GMT</Last-Modified>
        <Etag>"0x8D46CBD93FED46F"</Etag>
        <LeaseStatus>unlocked</LeaseStatus>
        <LeaseState>available</LeaseState>
        </Properties>
      </Container>
      <Container>
        <Name>container-5</Name>
        <Properties>
          <Last-Modified>Thu, 16 Mar 2017 22:41:39 GMT</Last-Modified>
          <Etag>"0x8D46CBD9C762815"</Etag>
          <LeaseStatus>unlocked</LeaseStatus>
          <LeaseState>available</LeaseState>
        </Properties>
      </Container>
  </Containers>
  <NextMarker />
</EnumerationResults>

Nachdem Sie nun mit dem Erstellen der Anforderung, dem Aufrufen des Diensts und dem Analysieren der Ergebnisse vertraut sind, geht es mit der Erstellung des Autorisierungsheaders weiter.

Erstellen des Autorisierungsheaders

Tipp

Azure Storage unterstützt die Microsoft Entra-Integration für Blobs und Warteschlangen. Microsoft Entra ID bietet eine wesentlich einfachere Oberfläche für die Autorisierung einer Anforderung an Azure Storage. Weitere Informationen zur Verwendung der Microsoft Entra ID zum Autorisieren von REST-Vorgängen finden Sie unter Autorisieren mit Microsoft Entra ID. Eine Übersicht über die Microsoft Entra-Integration in Azure Storage finden Sie unter Authentifizieren des Zugriffs auf Azure Storage mithilfe von Microsoft Entra ID.

Weitere Informationen zu Autorisierungskonzepten finden Sie unter Autorisieren von Anforderungen an Azure Storage.

Wir fassen hier die wesentlichen Punkte des Artikels zusammen und zeigen den Code.

Verwenden Sie zunächst die Autorisierung mit gemeinsam verwendetem Schlüssel. Der Autorisierungsheader hat das folgende Format:

Authorization="SharedKey <storage account name>:<signature>"  

Das Signaturfeld ist ein HMAC (Hash-based Message Authentication Code), der aus der Anforderung erstellt und mit dem SHA256-Algorithmus berechnet und anschließend per Base64-Codierung codiert wird.

In diesem Codeausschnitt wird das Format der Signaturzeichenfolge für den gemeinsam verwendeten Schlüssel veranschaulicht:

StringToSign = VERB + "\n" +  
               Content-Encoding + "\n" +  
               Content-Language + "\n" +  
               Content-Length + "\n" +  
               Content-MD5 + "\n" +  
               Content-Type + "\n" +  
               Date + "\n" +  
               If-Modified-Since + "\n" +  
               If-Match + "\n" +  
               If-None-Match + "\n" +  
               If-Unmodified-Since + "\n" +  
               Range + "\n" +  
               CanonicalizedHeaders +  
               CanonicalizedResource;  

Für Blobspeicher geben Sie „VERB“, „md5“, „content length“, „Canonicalized Headers“ und „Canonicalized Resource“ an. Die anderen Angaben können für dieses Beispiel leer gelassen werden. Fügen Sie jedoch \n ein, um anzugeben, dass sie leer sind.

Die Kanonisierung ist ein Prozess der Standardisierung von Daten mit mehr als einer möglichen Darstellung. In diesem Fall werden die Header und die Ressource standardisiert. Die kanonisierten Header beginnen mit „x-ms-“. Die kanonisierte Ressource ist der URI der Ressource, einschließlich des Speicherkontonamens und aller Abfrageparameter (z. B. ?comp=list). Die kanonisierte Ressource enthält auch alle zusätzlichen Abfrageparameter, die Sie möglicherweise hinzugefügt haben (z. B. timeout=60).

Wir beginnen mit den beiden kanonisierten Feldern, da sie erforderlich sind, um den Autorisierungsheader zu erstellen.

Vereinheitlichte Header

Rufen Sie zum Erstellen dieses Werts die Header ab, die mit „x-ms-“ beginnen, und sortieren Sie sie. Formatieren Sie sie anschließend in eine Reihe von [key:value\n]-Instanzen, die zu einer Zeichenfolge verkettet werden. In diesem Beispiel sehen die vereinheitlichten Header wie folgt aus:

x-ms-date:Fri, 17 Nov 2017 00:44:48 GMT\nx-ms-version:2017-07-29\n

Hier ist der Code angegeben, der zum Erstellen dieser Ausgabe verwendet wird:

private static string GetCanonicalizedHeaders(HttpRequestMessage httpRequestMessage)
{
    var headers = from kvp in httpRequestMessage.Headers
        where kvp.Key.StartsWith("x-ms-", StringComparison.OrdinalIgnoreCase)
        orderby kvp.Key
        select new { Key = kvp.Key.ToLowerInvariant(), kvp.Value };

    StringBuilder headersBuilder = new StringBuilder();

    foreach (var kvp in headers)
    {
        headersBuilder.Append(kvp.Key);
        char separator = ':';

        // Get the value for each header, strip out \r\n if found, then append it with the key.
        foreach (string headerValue in kvp.Value)
        {
            string trimmedValue = headerValue.TrimStart().Replace("\r\n", string.Empty);
            headersBuilder.Append(separator).Append(trimmedValue);

            // Set this to a comma; this will only be used
            // if there are multiple values for one of the headers.
            separator = ',';
        }

        headersBuilder.Append("\n");
    }

    return headersBuilder.ToString();
}

Vereinheitlichte Ressource

Dieser Teil der Signaturzeichenfolge steht für das Speicherkonto, auf das die Anforderung abzielt. Beachten Sie, dass der Anforderungs-URI http://contosorest.blob.core.windows.net/?comp=list lautet und den tatsächlichen Kontonamen enthält (hier contosorest). In diesem Beispiel wird Folgendes zurückgegeben:

/contosorest/\ncomp:list

Wenn Sie Abfrageparameter verwenden, sind diese ebenfalls in diesem Beispiel enthalten. Hier ist der Code angegeben, mit dem auch zusätzliche Abfrageparameter und Abfrageparameter mit mehreren Werten verarbeitet werden. Denken Sie daran, dass Sie diesen Code für alle REST-APIs erstellen. Sie möchten alle Möglichkeiten berücksichtigen, selbst wenn die ListContainers-Methode nicht alle benötigt.

private static string GetCanonicalizedResource(Uri address, string storageAccountName)
{
    // The absolute path will be "/" because for we're getting a list of containers.
    StringBuilder sb = new StringBuilder("/").Append(storageAccountName).Append(address.AbsolutePath);

    // Address.Query is the resource, such as "?comp=list".
    // This ends up with a NameValueCollection with 1 entry having key=comp, value=list.
    // It will have more entries if you have more query parameters.
    NameValueCollection values = HttpUtility.ParseQueryString(address.Query);

    foreach (var item in values.AllKeys.OrderBy(k => k))
    {
        sb.Append('\n').Append(item.ToLower()).Append(':').Append(values[item]);
    }

    return sb.ToString();
}

Nachdem die vereinheitlichten Zeichenfolgen nun festgelegt wurden, sehen wir uns an, wie der eigentliche Autorisierungsheader erstellt wird. Zunächst erstellen Sie eine Zeichenfolge mit der Nachrichtensignatur im Format StringToSign, das weiter oben in diesem Artikel beschrieben wurde. Dieses Konzept ist einfacher zu erklären, indem Kommentare im Code verwendet werden. Dies ist also die endgültige Methode, mit der der Autorisierungsheader zurückgegeben wird:

internal static AuthenticationHeaderValue GetAuthorizationHeader(
    string storageAccountName, string storageAccountKey, DateTime now,
    HttpRequestMessage httpRequestMessage, string ifMatch = "", string md5 = "")
{
    // This is the raw representation of the message signature.
    HttpMethod method = httpRequestMessage.Method;
    String MessageSignature = String.Format("{0}\n\n\n{1}\n{5}\n\n\n\n{2}\n\n\n\n{3}{4}",
                method.ToString(),
                (method == HttpMethod.Get || method == HttpMethod.Head) ? String.Empty
                  : httpRequestMessage.Content.Headers.ContentLength.ToString(),
                ifMatch,
                GetCanonicalizedHeaders(httpRequestMessage),
                GetCanonicalizedResource(httpRequestMessage.RequestUri, storageAccountName),
                md5);

    // Now turn it into a byte array.
    byte[] SignatureBytes = Encoding.UTF8.GetBytes(MessageSignature);

    // Create the HMACSHA256 version of the storage key.
    HMACSHA256 SHA256 = new HMACSHA256(Convert.FromBase64String(storageAccountKey));

    // Compute the hash of the SignatureBytes and convert it to a base64 string.
    string signature = Convert.ToBase64String(SHA256.ComputeHash(SignatureBytes));

    // This is the actual header that will be added to the list of request headers.
    AuthenticationHeaderValue authHV = new AuthenticationHeaderValue("SharedKey",
        storageAccountName + ":" + signature);
    return authHV;
}

Wenn Sie diesen Code ausführen, sieht die resultierende MessageSignature wie folgt aus:

GET\n\n\n\n\n\n\n\n\n\n\n\nx-ms-date:Fri, 17 Nov 2017 01:07:37 GMT\nx-ms-version:2017-07-29\n/contosorest/\ncomp:list

Hier ist der endgültige Wert für AuthorizationHeader angegeben:

SharedKey contosorest:Ms5sfwkA8nqTRw7Uury4MPHqM6Rj2nfgbYNvUKOa67w=

Der AuthorizationHeader ist der letzte Header, der vor dem Posten der Antwort in Anforderungsheadern angeordnet wird.

Dies sind alle Informationen, die zum Zusammenstellen einer Klasse erforderlich sind, mit der Sie eine Anforderung zum Aufrufen der REST-APIs von Storage-Diensten verwenden können.

Beispiel: Auflisten von Blobs

Wir sehen uns nun an, wie Sie den Code zum Aufrufen des Vorgangs „List Blobs“ (Blobs auflisten) für den Container container-1 ändern. Dieser Code ist nahezu identisch mit dem Code zum Auflisten von Containern. Die einzigen Unterschiede sind der URI und die Vorgehensweise beim Analysieren der Antwort.

Wenn Sie sich die Referenzdokumentation für ListBlobs ansehen, sehen Sie, dass die Methode GET ist und der RequestURI wie folgt lautet:

https://myaccount.blob.core.windows.net/container-1?restype=container&comp=list

Ändern Sie unter ListContainersAsyncREST den Code, mit dem der URI auf die API für ListBlobs festgelegt wird. Der Containername lautet container-1.

String uri =
    string.Format("http://{0}.blob.core.windows.net/container-1?restype=container&comp=list",
      storageAccountName);

Ändern Sie anschließend den Code an der Stelle, an der die Antwort verarbeitet wird, damit nicht nach Containern gesucht wird, sondern nach Blobs.

foreach (XElement container in x.Element("Blobs").Elements("Blob"))
{
    Console.WriteLine("Blob name = {0}", container.Element("Name").Value);
}

Wenn Sie dieses Beispiel ausführen, erhalten Sie beispielsweise folgende Ergebnisse:

Vereinheitlichte Header:

x-ms-date:Fri, 17 Nov 2017 05:16:48 GMT\nx-ms-version:2017-07-29\n

Vereinheitlichte Ressource:

/contosorest/container-1\ncomp:list\nrestype:container

Nachrichtensignatur:

GET\n\n\n\n\n\n\n\n\n\n\n\nx-ms-date:Fri, 17 Nov 2017 05:16:48 GMT
  \nx-ms-version:2017-07-29\n/contosorest/container-1\ncomp:list\nrestype:container

Autorisierungsheader:

SharedKey contosorest:uzvWZN1WUIv2LYC6e3En10/7EIQJ5X9KtFQqrZkxi6s=

Die folgenden Werte stammen aus Fiddler:

Anforderung:

GET http://contosorest.blob.core.windows.net/container-1?restype=container&comp=list HTTP/1.1

Anforderungsheader:

x-ms-date: Fri, 17 Nov 2017 05:16:48 GMT
x-ms-version: 2017-07-29
Authorization: SharedKey contosorest:uzvWZN1WUIv2LYC6e3En10/7EIQJ5X9KtFQqrZkxi6s=
Host: contosorest.blob.core.windows.net
Connection: Keep-Alive

Nach der Ausführung zurückgegebener Statuscode bzw. Antwortheader:

HTTP/1.1 200 OK
Content-Type: application/xml
Server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: 7e9316da-001e-0037-4063-5faf9d000000
x-ms-version: 2017-07-29
Date: Fri, 17 Nov 2017 05:20:21 GMT
Content-Length: 1135

Antworttext (XML): In dieser XML-Antwort wird die Liste mit Blobs und den dazugehörigen Eigenschaften angezeigt.

<?xml version="1.0" encoding="utf-8"?>
<EnumerationResults
    ServiceEndpoint="http://contosorest.blob.core.windows.net/" ContainerName="container-1">
    <Blobs>
        <Blob>
            <Name>DogInCatTree.png</Name>
            <Properties><Last-Modified>Fri, 17 Nov 2017 01:41:14 GMT</Last-Modified>
            <Etag>0x8D52D5C4A4C96B0</Etag>
            <Content-Length>419416</Content-Length>
            <Content-Type>image/png</Content-Type>
            <Content-Encoding />
            <Content-Language />
            <Content-MD5 />
            <Cache-Control />
            <Content-Disposition />
            <BlobType>BlockBlob</BlobType>
            <LeaseStatus>unlocked</LeaseStatus>
            <LeaseState>available</LeaseState>
            <ServerEncrypted>true</ServerEncrypted>
            </Properties>
        </Blob>
        <Blob>
            <Name>GuyEyeingOreos.png</Name>
            <Properties>
                <Last-Modified>Fri, 17 Nov 2017 01:41:14 GMT</Last-Modified>
                <Etag>0x8D52D5C4A25A6F6</Etag>
                <Content-Length>167464</Content-Length>
                <Content-Type>image/png</Content-Type>
                <Content-Encoding />
                <Content-Language />
                <Content-MD5 />
                <Cache-Control />
                <Content-Disposition />
                <BlobType>BlockBlob</BlobType>
                <LeaseStatus>unlocked</LeaseStatus>
                <LeaseState>available</LeaseState>
                <ServerEncrypted>true</ServerEncrypted>
            </Properties>
            </Blob>
        </Blobs>
    <NextMarker />
</EnumerationResults>

Zusammenfassung

In diesem Artikel haben Sie gelernt, wie eine Anforderung an die Blobspeicher-REST-API gesendet wird. Mit der Anforderung können Sie eine Liste der Container oder eine Liste der Blobs in einem Container abrufen. Sie haben erfahren, wie Sie die Autorisierungssignatur für den REST-API-Aufruf erstellen und diese in der REST-Anforderung verwenden. Zuletzt wurde gezeigt, wie Sie die Antwort untersuchen.

Nächste Schritte