Вызов операций REST API с авторизацией общего ключа

В этой статье показано, как вызвать операцию REST API служба хранилища Azure путем создания авторизованного запроса REST с помощью C#. После того как вы узнаете, как вызвать операцию REST API для служба хранилища BLOB-объектов, можно выполнить аналогичные действия для любой другой операции REST служба хранилища Azure.

Необходимые компоненты

Пример приложения содержит список контейнеров BLOB-объектов в учетной записи хранения. Чтобы выполнить код, описанный в этой статье, необходимо следующее.

  • Установите Visual Studio и включите рабочую нагрузку разработки Azure. Этот пример был создан с помощью Visual Studio 2019. Если вы используете другую версию, руководство может немного отличаться.

  • Подписка Azure. Если у вас еще нет подписки Azure, создайте бесплатную учетную запись, прежде чем начинать работу.

  • Учетная запись хранения общего назначения. Если у вас еще нет учетной записи хранения Azure, создайте ее.

  • Пример в этой статье показывает, как перечислять контейнеры в учетной записи хранения. Чтобы просмотреть выходные данные, добавьте некоторые контейнеры BLOB-объектов в учетную запись хранения перед началом работы.

Загрузка примера приложения

Образец приложения представляет собой консольное приложение, написанное на языке C#.

Используйте команду git, чтобы скачать копию приложения в среду разработки.

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

Эта команда клонирует репозиторий в локальную папку git. Чтобы открыть решение Visual Studio, перейдите в папку storage-dotnet-rest-api-with-auth и откройте файл служба хранилища RestApiAuth.sln.

О REST

Передача состояния представления (REST) — это архитектура, которая позволяет взаимодействовать со службой через интернет-протокол, например HTTP/HTTPS. REST не зависит от программного обеспечения, выполняемого на сервере или клиенте. REST API можно вызывать с любой платформы, которая поддерживает HTTP/HTTPS. Вы можете написать приложение, которое работает на Mac, Windows, Linux, телефоне или планшете Android, iPhone, iPod или веб-сайте и использовать один и тот же REST API для всех этих платформ.

Вызов REST API состоит из запроса, сделанного клиентом, и ответа, возвращаемого службой. В запросе вы отправляете URL-адрес со сведениями об операции, которую необходимо вызвать, ресурсе, по отношению к которому будет выполняться действие, параметрах запроса и заголовках, а также (в зависимости от вызываемой операции) полезных данных. Ответ службы содержит код состояния, набор заголовков ответа и, в зависимости от вызываемой операции, полезные данные.

Сведения о примере приложения

Пример приложения содержит список контейнеров в учетной записи хранения. После того, как вы поймете, как сведения в руководстве коррелируют с фактическим кодом, другие вызовы REST будет легче понять.

Если вы посмотрите на API REST службы BLOB-объектов, то увидите, что все операции можно выполнять в хранилище BLOB-объектов. Клиентские библиотеки хранилища — это оболочки по интерфейсу REST API, что упрощает доступ к ресурсам хранилища без использования интерфейсов REST API напрямую. Однако иногда может потребоваться использовать REST API вместо клиентской библиотеки хранилища.

Операция перечисления контейнеров

В этой статье рассматривается операция "Контейнеры списка". Следующие сведения помогут вам понять некоторые поля в запросе и ответе.

Метод запроса: GET. Эта команда является методом HTTP, который вы указываете как свойство объекта запроса. Другие значения для этой команды включают HEAD, PUT и DELETE в зависимости от вызываемого API.

URI запроса: https://myaccount.blob.core.windows.net/?comp=list. URI запроса создается из конечной точки учетной записи хранилища BLOB-объектов https://myaccount.blob.core.windows.net и строки ресурса /?comp=list.

Параметры URI: существуют дополнительные параметры запроса, которые вы можете использовать при вызове ListContainers. Некоторыми из этих параметров являются timeout для вызова (в секундах) и prefix, который используется для фильтрации.

Другим полезным параметром является maxresults. Если доступно больше контейнеров, чем это значение, текст ответа будет содержать элемент NextMarker, который указывает, что следующий контейнер будет возвращен при следующем запросе. Чтобы использовать эту функцию, следует указать NextMarker в качестве параметра маркера в URI при выполнении следующего запроса. При использовании этой функции это аналогично просмотру результатов.

Чтобы использовать дополнительные параметры, добавьте их в строку ресурса со значением, например, в этом примере:

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

Заголовки запросов: в этом разделе перечислены обязательные и необязательные заголовки запросов. Три заголовка являются обязательными: Authorization, x-ms-date (содержит время запроса в формате UTC) и x-ms-version (версия интерфейса REST API для использования). Включение x-ms-client-request-id в заголовках является необязательным. Значение этого поля можно задать всем, и оно записывается в журналы аналитики хранилища при включении ведения журнала.

Текст запроса: текст запроса для ListContainers отсутствует. Текст запроса используется для всех операций PUT при отправке больших двоичных объектов, включая SetContainerAccessPolicy. Текст запроса позволяет отправлять xml-список хранимых политик доступа для применения. Хранимые политики доступа рассматриваются в статье Использование подписанных URL-адресов (SAS).

Код состояния ответа: сообщает о любых кодах состояния, о которых вам нужно знать. В этом примере кодом состояния HTTP является 200 — это нормально. Полный список кодов состояния HTTP см. на этой странице. Коды ошибок, относящихся к хранилищу интерфейсов REST API, см. в статье Common REST API Error Codes (Общие коды ошибок API-интерфейса REST).

Заголовки ответов: к ним относятся Content Type; x-ms-request-id (идентификатор запроса, который вы передали); x-ms-version (обозначает версию используемой службы BLOB-объектов); Date (в формате UTC; указывает, в какое время был сделан запрос).

Текст ответа: это поле является XML-структурой, предоставляющей запрашиваемые данные. В этом примере ответ представляет собой список контейнеров и их свойств.

Создание запроса REST

Для обеспечения безопасности при запуске в рабочей среде всегда используйте HTTPS вместо HTTP. В этом упражнении мы используем HTTP, чтобы просмотреть данные запроса и ответа. Чтобы просмотреть сведения запроса и ответа в фактических вызовах REST, загрузите Fiddler или похожее приложение. В решении Visual Studio имя учетной записи хранения и ключ жестко запрограммированы в классе. Метод ListContainersAsyncREST передает имя учетной записи хранения и ключ учетной записи хранения методам, которые используются для создания различных компонентов запроса REST. В случае реального приложения имя и ключ учетной записи хранения будут находиться в файле конфигурации, переменных среды или извлекаться из хранилища Azure Key Vault.

В нашем примере проекта код для создания заголовка авторизации находится в отдельном классе, Идея в том, что вы можете взять этот класс целиком и добавить его в собственное решение "как есть". Код заголовка Authorization нормально работает для большинства вызовов к API REST службы хранилища Azure.

Чтобы создать запрос, являющийся объектом HttpRequestMessage, перейдите в ListContainersAsyncREST в Program.cs. Для создания запроса, необходимо:

  • Создайте URI, используемый для вызова службы.
  • Создайте объект HttpRequestMessage и настройте полезную нагрузку. Полезная нагрузка равна нулю для ListContainersAsyncREST, потому что мы ничего не передаем.
  • Добавьте заголовки запросов для x-ms-date и x-ms-version.
  • Получите заголовок авторизации и добавьте его.

Необходимые базовые сведения:

  • Для ListContainers методом является GET. Это значение устанавливается при создании экземпляра запроса.
  • Ресурс является частью запроса URI, который указывает на вызываемый API, поэтому значением будет /?comp=list. Как отмечалось ранее, ресурс находится на странице справочной документации о ListContainers API.
  • URI создается путем создания конечной точки службы BLOB-объектов для этой учетной записи хранения и сцепки ресурсов. Значением для URI запроса будет http://contosorest.blob.core.windows.net/?comp=list.
  • Для ListContainers requestBody имеет значение null и не имеет дополнительных заголовков.

Различные API могут иметь другие параметры для передачи, например ifMatch. Пример того, где вы можете использовать ifMatch, — вызов PutBlob. В этом случае установите ifMatch для тега сущности, и он обновит большой двоичный объект только в том случае, если тег сущности, который вы предоставляете, соответствует текущему тегу в большом двоичном объекте. Если другой пользователь обновил большой двоичный объект после получения eTag, их изменение не переопределяется.

Сначала следует задать uri и requestPayload.

// 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;

Затем создайте экземпляр запроса, установив в качестве метода GET и предоставив URI.

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

Добавьте заголовки запроса для x-ms-date и x-ms-version. В этом месте кода также можно добавить дополнительные заголовки запросов, необходимые для вызова. В этом примере нет дополнительных заголовков. Примером API, который передается в дополнительных заголовках, является операция задания списка управления доступом для контейнера. Этот вызов API добавляет заголовок, называемый x-ms-blob-public-access, и значение для уровня доступа.

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

Вызовите метод, который создает заголовок авторизации и добавьте его в заголовки запросов. Заголовок авторизации создается позже в статье. Именем метода является GetAuthorizationHeader, которое можно увидеть в этом фрагменте кода:

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

На этом этапе httpRequestMessage содержит запрос REST с заголовками авторизации.

Отправка запроса

Теперь, когда запрос создан, можно вызвать метод SendAsync, чтобы отправить его в службу хранилища Azure. Убедитесь, что значение кода состояния отклика — 200. Это означает, что операция выполнена успешно. Затем выполните синтаксический анализ ответа. В этом случае можно получить XML-список контейнеров. Давайте рассмотрим код вызова метода GetRESTRequest, после чего создадим запрос, выполним его и изучим ответ со списком контейнеров.

    // 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);
            }
        }
    }
}

Если во время вызова SendAsync вы запускаете средство прослушивания сети, например Fiddler, вы можете увидеть сведения о запросе и ответе. Давай посмотрим. Имя учетной записи хранения — contosorest.

Запрос:

GET /?comp=list HTTP/1.1

Заголовки запросов:

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

Код состояния и заголовки ответов возвращены после выполнения:

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

Текст ответа (XML): для операции ListContainers отображается список контейнеров и их свойства.

<?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>

Теперь, когда вы знаете, как создавать запросы, вызывать службу и анализировать результаты, давайте посмотрим, как создать заголовок авторизации.

Создание заголовка авторизации

Совет

служба хранилища Azure поддерживает интеграцию Microsoft Entra для больших двоичных объектов и очередей. Идентификатор Microsoft Entra предоставляет гораздо более простой интерфейс для авторизации запроса на служба хранилища Azure. Дополнительные сведения об использовании идентификатора Microsoft Entra для авторизации операций REST см. в разделе "Авторизация с помощью идентификатора Microsoft Entra". Общие сведения об интеграции Microsoft Entra с служба хранилища Azure см. в статье "Проверка подлинности доступа к служба хранилища Azure с помощью идентификатора Microsoft Entra".

Дополнительные сведения о концепциях авторизации см. в статье "Авторизация запросов на служба хранилища Azure".

Давайте уточним, что необходимо, и посмотрим на код.

Во-первых, используйте авторизацию на основе общего ключа. Формат заголовка авторизации выглядит следующим образом:

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

Поле подписи — это код аутентификации сообщения на основе хэш-кода (HMAC), созданный из запроса и вычисленный с использованием алгоритма SHA256, а затем закодированный с использованием кодировки Base64.

Этот фрагмент кода отображает формат строки подписи общего ключа:

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;  

Для хранилища BLOB-объектов вы указываете VERB, md5, длину содержимого, канонические заголовки и канонический ресурс. Вы можете оставить остальные пустыми для этого примера, но поместить его \n , чтобы указать, что они пусты.

Канонизация — это процесс стандартизации данных, которые имеют более одного возможного представления. В этом случае вы стандартизированы заголовки и ресурс. Канонизированные заголовки — это заголовки, начинающиеся с x-ms-. Канонизированный ресурс — это URI ресурса, включая имя учетной записи хранения и все параметры запроса (например ?comp=list). Канонизированный ресурс также включает любые дополнительные параметры запроса, которые вы могли добавить, например timeout=60, например.

Начнем с двух канонических полей, так как они необходимы для создания заголовка авторизации.

Канонические заголовки

Чтобы создать это значение, загрузите заголовки, начинающиеся с x-ms-, и отсортируйте их, а затем отформатируйте их в строку экземпляров [key:value\n], объединенных в одну строку. В этом примере канонические заголовки будут выглядеть следующим образом:

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

Вот код, используемый для создания этих выходных данных:

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();
}

Канонический ресурс

Эта часть строки подписи представляет собой учетную запись хранения, предназначенную для запроса. Помните, что URI запроса является http://contosorest.blob.core.windows.net/?comp=list с именем фактической учетной записи (в данном случае contosorest). В этом примере возвращается следующее:

/contosorest/\ncomp:list

Если у вас есть параметры запроса, они также приведены в этом примере. Вот код, который также обрабатывает дополнительные параметры запроса и параметры запроса с несколькими значениями. Помните, что вы создаете этот код для всех интерфейсов API REST, поэтому в него необходимо включить все возможности, даже если методу ListContainers требуются не все из них.

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();
}

Теперь, когда канонические строки заданы, давайте посмотрим, как создать сам заголовок авторизации. Сначала нужно создать строку подписи сообщения в формате StringToSign, ранее описанную в этой статье. Эту концепцию легче объяснить с помощью комментариев в коде. Ниже приведен окончательный метод, который возвращает заголовок авторизации:

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;
}

При выполнении этого кода, полученный MessageSignature выглядит следующим образом:

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

Вот конечное значение для AuthorizationHeader:

SharedKey contosorest:Ms5sfwkA8nqTRw7Uury4MPHqM6Rj2nfgbYNvUKOa67w=

AuthorizationHeader — это последний заголовок, помещенный в заголовки запроса перед отправкой ответа.

Это все, что вам нужно знать, чтобы собрать класс, который вы можете использовать для создания запроса для вызова API-интерфейсов REST служб хранилища.

Пример: вывод списка BLOB-объектов

Давайте рассмотрим, как изменить код, чтобы вызвать операцию вывода списка BLOB-объектов для контейнера container-1. Это почти такой же код для перечисления контейнеров, единственными отличиями которого являются URI и то, как вы анализируете ответ.

Если взглянуть на справочную документацию по ListBlobs, обнаружится, что методом является GET, а свойством RequestURI является:

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

В ListContainersAsyncREST измените код, который устанавливает URI в API для ListBlob. Имя контейнера — container-1.

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

Затем, там где вы обрабатываете ответ, измените код, чтобы найти BLOB-объекты вместо контейнеров.

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

При запуске этого примера можно получить следующие результаты:

Канонические заголовки:

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

Канонический ресурс:

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

Сигнатура сообщения:

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

Заголовок авторизации:

SharedKey contosorest:uzvWZN1WUIv2LYC6e3En10/7EIQJ5X9KtFQqrZkxi6s=

В Fiddler доступны следующие значения:

Запрос:

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

Заголовки запросов:

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

Код состояния и заголовки ответов возвращены после выполнения:

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

Текст ответа (XML): этот ответ XML отображает список BLOB-объектов и их свойства.

<?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>

Итоги

В этой статье вы узнали, как создать запрос к API REST хранилища BLOB-объектов, чтобы получить список контейнеров или список BLOB-объектов в контейнере. Вы узнали, как создать подпись авторизации для вызова REST API, как использовать ее в запросе REST и, наконец, как проверить ответ.

Следующие шаги