2013-09-04 3 views
3

Что я пытаюсь сделать, так это подключиться к списку Blazs API хранения Azure Storage Rest. Ссылка: http://msdn.microsoft.com/en-us/library/windowsazure/dd135734.aspxAzure - вызов Storage rest api для списка blobs

Я попытался следовать http://msdn.microsoft.com/en-us/library/windowsazure/dd179428.aspx, чтобы указать заголовок авторизации, однако я получаю ошибку 403 - запрещено.

Код:

Uri address = new Uri("https://account.blob.core.windows.net/$logs?restype=container&comp=list"); 
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(address); 
req.Headers["x-ms-date"] = "2013-09-04"; 
req.Headers["x-ms-version"] = "2012-02-12"; 
req.Method = "GET"; 

string StringToSign = "GET\n" 
    + "\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 
    + "x-ms-date: 2013-09-04\nx-ms-version:2012-02-12\n" // headers 
    + "/account/blob\ncomp:list\nrestype:container"; // resources 

string accountName = "account"; 
string key = Convert.ToBase64String(Encoding.Default.GetBytes(StringToSign)); 
req.Headers["Authorization"] = string.Format("SharedKey {0}:{1}", accountName, key); 

HttpWebResponse resp = req.GetResponse() as HttpWebResponse; 

Можно ли увидеть какие-либо ошибки? Есть ли инструмент, который может генерировать ключ? Одна вещь, о которой я не уверен, - это кодирование/хэширование строки правильно.

Спасибо, Andrew

Обновление с последним кодом. Этот код дает мне Forbidden ошибку.

DateTime dt = DateTime.UtcNow; 
string StringToSign = "GET\n" 
    + "\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 
    + "x-ms-date: " + dt.ToString("R") + "\nx-ms-version:2012-02-12\n" // headers 
    + "/account/$logs\ncomp:list\nrestype:container"; 

string auth = SignThis(StringToSign, "accountkey", "account"); 
string method = "GET"; 
string urlPath = "https://account.blob.core.windows.net/$logs?restype=container&comp=list"; 
Uri uri = new Uri(urlPath); 
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); 
request.Method = method; 
request.Headers.Add("x-ms-date", dt.ToString("R")); 
request.Headers.Add("x-ms-version", "2012-02-12"); 
request.Headers.Add("Authorization", auth); 

using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) 
{ 
} 
+0

Когда вы говорите «есть инструмент, который может генерировать ключ», это делает меня подозрительным. Вы получаете ключ от страницы лазурного хранения на лазурном портале управления? – paqogomez

+0

Да. Я новичок в Azure - у меня есть доступ к порталу, я имею в виду использовать ключ, который указан на портале? Или создать ключ через код выше? – andrewb

+0

Теперь я вижу, что вы делаете с помощью «StringToSign». Это не то, что пример пытается вам рассказать. вы даете результат, а не значение для отправки. Позвольте мне что-то попробовать. Перетаскивание - это то, что у меня есть весь этот код на работе. – paqogomez

ответ

4

Есть некоторые проблемы с кодом выше. Но прежде всего, прежде всего вам понадобится ключ для вашей учетной записи хранилища. Вы можете получить его с Windows Azure Portal. Нажмите на имя учетной записи для хранения на портале, а затем нажмите на «МЕНЕДЖЕР доступа к ключам», как показано на скриншоте ниже:

enter image description here

Теперь для вопросов:

Путь вы создаете Недопустимый заголовок авторизации. Для создания заголовка авторизации вам потребуется имя учетной записи, ключ учетной записи и StringToSign из вашего кода выше. Попробуйте этот код:

private static String SignThis(String StringToSign, string Key, string Account) 
     { 
      String signature = string.Empty; 
      byte[] unicodeKey = Convert.FromBase64String(Key); 
      using (HMACSHA256 hmacSha256 = new HMACSHA256(unicodeKey)) 
      { 
       Byte[] dataToHmac = System.Text.Encoding.UTF8.GetBytes(canonicalizedString); 
       signature = Convert.ToBase64String(hmacSha256.ComputeHash(dataToHmac)); 
      } 

      String authorizationHeader = String.Format(
        CultureInfo.InvariantCulture, 
        "{0} {1}:{2}", 
        "SharedKey", 
        Account, 
        signature); 

      return authorizationHeader; 
     } 

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

2-я вещь, которую я заметил, заключалась в том, что в коде для StringToSign вы не передаете имя контейнера. Так что ваш StringToSign должно быть:

string StringToSign = "GET\n" 
    + "\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 
    + "x-ms-date: 2013-09-04\nx-ms-version:2012-02-12\n" // headers 
    + "/account/$logs\ncomp:list\nrestype:container"; // resources 

Вы упомянули, что вы совершенно новой для Windows Azure. Если я могу предложить - внедрение REST API было сделано еще несколькими людьми ранее. Пожалуйста, взгляните на то, что они сделали, вместо того, чтобы пытаться сделать то же самое снова. Вы можете найти эти ссылки полезны:

http://convective.wordpress.com/2010/08/18/examples-of-the-windows-azure-storage-services-rest-api/

http://azurestoragesamples.codeplex.com/ - Посмотрите на реализацию REST API в этом проекте.

UPDATE

Вот рабочий код (просто изменить имя учетной записи, ключ и имя контейнера)

static void ListContainers() 
{ 
    string Account = "account"; 
    string Key = "key"; 
    string Container = "$logs"; 
    DateTime dt = DateTime.UtcNow; 
    string StringToSign = String.Format("GET\n" 
     + "\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 
     + "x-ms-date:" + dt.ToString("R") + "\nx-ms-version:2012-02-12\n" // headers 
     + "/{0}/{1}\ncomp:list\nrestype:container", Account, Container); 

    string auth = SignThis(StringToSign, Key, Account); 
    string method = "GET"; 
    string urlPath = string.Format("https://{0}.blob.core.windows.net/{1}?restype=container&comp=list", Account, Container); 
    Uri uri = new Uri(urlPath); 
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); 
    request.Method = method; 
    request.Headers.Add("x-ms-date", dt.ToString("R")); 
    request.Headers.Add("x-ms-version", "2012-02-12"); 
    request.Headers.Add("Authorization", auth); 

    using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) 
    { 
    } 
} 

Надеется, что это помогает.

+0

Спасибо за подробный ответ. Несколько вещей: в SignThis вы ссылаетесь на переменную, называемую canonicalizedString, я полагаю, это должно быть StringToSign? Во-вторых, что такое canonicalizedString? В-третьих, когда я запускаю этот код, мне все равно запрещается, а создаваемый ключ отличается при каждом выполнении, верно? – andrewb

+0

Извините ... мой плохой ... вырезать/вставить ошибку: P. Да, это должно быть 'StringToSign'. Таким образом, в основном 'StringToSign' является canonicalizedString, который используется для создания заголовка авторизации. Будет ли возможно обновить исходный пост обновленным кодом, чтобы мы точно знали, что происходит. –

+0

Добавлен код. В переменной StringToSign мне нужно включить все поля, даже если у меня нет значения для этого поля? – andrewb

Смежные вопросы