开发者

How to format azure table storage request from iphone in Object-c

开发者 https://www.devze.com 2023-01-23 12:18 出处:网络
I need help getting my headers correct for an azure table storage request from an iPhone app. I\'ve been using these two posts to try and get the encryption of the key right but I\'m still having trou

I need help getting my headers correct for an azure table storage request from an iPhone app. I've been using these two posts to try and get the encryption of the key right but I'm still having trouble: iPhone and HMAC-SHA-1 encoding Objective-C sample code for HMAC-SHA1 The service is returning an error for my request: Server failed to authenticate the request with this error:

Make sure the value of Authorization header is formed correctly including the signature.

I am using the 开发者_开发问答following code to make the request:

NSDate *now = [[NSDate alloc] init];
    NSString *dateString = [self rfc1123String:now];

    NSString *messageToSign = [NSString stringWithFormat:@"%@\n/%@/%@", dateString, AZURE_ACCOUNT_NAME, table];

    [Base64 initialize];
    //xxx in my code is my primary access shared key
    NSString *key = @"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";

    const char *cKey = [key cStringUsingEncoding:NSUTF8StringEncoding];
    const char *cData = [messageToSign cStringUsingEncoding:NSUTF8StringEncoding];

    unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH];

    CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC);

    NSData *HMAC = [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)];


    NSString *hash = [Base64 encode:HMAC];

    NSLog(@"Encoded hash: %@", hash);

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    [request addValue:[NSString stringWithFormat:@"SharedKeyLite %@:%@", AZURE_ACCOUNT_NAME, hash] forHTTPHeaderField:@"Authorization"];
    [request addValue:dateString forHTTPHeaderField:@"x-ms-date"];
    [request addValue:@"application/atom+xml, application/xml" forHTTPHeaderField:@"Accept"];
    [request addValue:@"UTF-8" forHTTPHeaderField:@"Accept-Charset"];
    NSLog(@"Headers: %@", [request allHTTPHeaderFields]);
    NSLog(@"URL: %@", [[request URL] absoluteString]);
    return request;

Which results in these headers being generated for the request:

Accept = "application/atom+xml, application/xml";
    "Accept-Charset" = "UTF-8";
    Authorization = "SharedKeyLite powderdayalarm:xwT1purDtREtxauVr6Bhvdz/2ObLh2J0lMw/prBBQBE=";
    "X-Ms-Date" = "Fri, 05 Nov 2010 18:26:00 GMT";

The specification for the request is here: http://msdn.microsoft.com/en-us/library/dd179428.aspx Which refers to the following:

This format supports Shared Key and Shared Key Lite for all versions of the Table service, and Shared Key Lite for the 2009-09-19 version of the Blob and Queue services. This format is identical to that used with previous versions of the storage services. Construct the CanonicalizedResource string in this format as follows:

  1. Beginning with an empty string (""), append a forward slash (/), followed by the name of the account that owns the resource being accessed.

  2. Append the resource's encoded URI path. If the request URI addresses a component of the resource, append the appropriate query string. The query string should include the question mark and the comp parameter (for example, ?comp=metadata). No other parameters should be included on the query string.

Encoding the Signature

To encode the signature, call the HMAC-SHA256 algorithm on the UTF-8-encoded signature string and encode the result as Base64. Use the following format (shown as pseudocode): Copy

Signature=Base64(HMAC-SHA256(UTF8(StringToSign)))

I can't seem to get to the root of this one. And it doesn't seem like too many people are making azure requests form the iphone :).

Thanks Scott


Smarx explained the best practice to me on the Azure forum. Here is what he wrote: There are two secure ways to access storage from the client:

1.Use Shared Access Signatures with blobs. Server-side, you can generate the signature (basically a signed URL), and that signature is limited in scope (maybe to a particular blob, particular permissions, and a limited amount of time). 2.Only access a web service from the client, and have the web service access storage. In both cases, there's a server in between, much like in a web app. (The browser never talks to your SQL database... it talks to your website, which then talks to the database.)

0

精彩评论

暂无评论...
验证码 换一张
取 消