简体   繁体   中英

Windows Azure REST API SharedKeyLite Authentication (Storage Emulator)

I'm trying to create the right authentication headers for Windows Azure REST API queries (specifically, listing tables), but all of my queries return with 403 errors. I've read every doc I can find, but none of the copy-pasted code seems to work either. Here's what I've cobbled together, using the Storage Emulator:

    static String CreateAuthorizationHeader(String canonicalizedString)
    {
        String signature = String.Empty;
        string storageAccountKey = "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==";

        using (HMACSHA256 hmacSha256 = new HMACSHA256(Convert.FromBase64String(storageAccountKey)))
        {
            Byte[] dataToHmac = System.Text.Encoding.UTF8.GetBytes(canonicalizedString);
            signature = Convert.ToBase64String(hmacSha256.ComputeHash(dataToHmac));
        }

        return String.Format("devstoreaccount1:" + signature);
    }

    static void ListTables()
    {
        HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, new Uri("http://127.0.0.1:10002/devstoreaccount1/Tables"));
        if(request.Headers.Date.HasValue) {
            Console.WriteLine("Has Date");
            return;
        }
        string date = DateTime.UtcNow.ToString("R");
        request.Headers.Add("x-ms-date", date);

        string stringToSign =
            string.Format(
                "{0}\n{1}",
                date,
                "/devstoreaccount1/Tables");
        Console.Write("signing:\n{0}\n\n", stringToSign);

        String authorizationHeader = CreateAuthorizationHeader(stringToSign);
        request.Headers.Authorization = new AuthenticationHeaderValue("SharedKeyLite", authorizationHeader);

        Console.Write("Request string:\n{0}\n\n", request.ToString());

        var httpClient = new HttpClient();
        HttpResponseMessage response = httpClient.SendAsync(request).Result;
        if (!response.IsSuccessStatusCode)
        {
            Console.Write("Status was {0:d} ({0}): {1}", response.StatusCode, response.ReasonPhrase);
            return;
        }

        Console.WriteLine(response.Content.ReadAsStringAsync().Result);
    }

This is the output :

signing:
Fri, 26 Sep 2014 19:13:57 GMT
/devstoreaccount1/Tables

Request string:
Method: GET, RequestUri: 'http://127.0.0.1:10002/devstoreaccount1/Tables', Version: 1.1, Content: <null>, Headers:
{
  x-ms-date: Fri, 26 Sep 2014 19:13:57 GMT
  Authorization: SharedKeyLite devstoreaccount1:9nDo0c6fy/cUcImLCKMHvPYKba56xdh5l5pWDMhh3+0=
}

Status was 403 (Forbidden): Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.

Can anybody spot a flaw in this? Could somebody post an example ListTables request string using these same constraints and assumptions, including the resulting signature string?

Thanks!

Based on the documentation here (Section: Constructing the Canonicalized Resource string), you would need to put storage account name twice.

If you are authenticating against the storage emulator, the account name will appear twice in the CanonicalizedResource string. This is expected. If you are authenticating against Azure storage services, the account name will appear only one time in the CanonicalizedResource string.

Based on this, please try with the following:

string stringToSign =
            string.Format(
                "{0}\n{1}",
                date,
                "/devstoreaccount1/devstoreaccount1/Tables");

This should do the trick.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM