问题
I'm building a mac application and not using the AWS iOS SDK. The GET request I'm trying to build should follow this general format:
"Authorization: AWS " + AWSAccessKeyId + ":" + base64(hmac-sha1(VERB + "\n"
+ CONTENT-MD5 + "\n"
+ CONTENT-TYPE + "\n"
+ DATE + "\n"
+ CanonicalizedAmzHeaders + "\n"
+ CanonicalizedResource))
As provided as "pseudo syntax" in the Amazon docs. I've been searching all over for clarification and it seems that according to a lot of people, many of the fields in the base64 hash are optional.
Below is what I came up with so far. But the response I get is an error from AWS saying "Unsupported Authorization Type" making reference to the 'Authorization' field in the header. I'm getting really stumped here. Any insight into how to debug or fix this?
Is there any other way to go about generating pre-signed urls in Obj C for S3?
-(NSURLRequest*) requestWithURL: (NSString*) reqURL
{
NSMutableURLRequest *mutableRequest = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:reqURL]];
NSString* headerField = @"Authorization: ";
NSString* stringToSign = @"GET\n\n\n\n\n";
NSString* hash = [self hmacsha1:stringToSign key:SECRET_KEY];
NSString *authHeader = [NSString stringWithFormat: @"AWS%@:%@", ACCESS_KEY_ID, hash];
NSURLResponse *resp = nil;
NSError *error = nil;
[mutableRequest addValue:authHeader forHTTPHeaderField:headerField];
NSData *response = [NSURLConnection sendSynchronousRequest: mutableRequest returningResponse: &resp error: &error];
NSString *responseString = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
return (NSURLRequest*) mutableRequest;
}
- (NSString *)hmacsha1:(NSString *)text key:(NSString *)secret {
NSData *secretData = [secret dataUsingEncoding:NSUTF8StringEncoding];
NSData *clearTextData = [text dataUsingEncoding:NSUTF8StringEncoding];
unsigned char result[20];
CCHmac(kCCHmacAlgSHA1, [secretData bytes], [secretData length], [clearTextData bytes], [clearTextData length], result);
char base64Result[32];
size_t theResultLength = 32;
NSData *theData = [NSData dataWithBytes:base64Result length:theResultLength];
NSString* encodedData = [NSString stringWithFormat:@"%@",[theData base64Encoding]];
return encodedData;
}
The base64 encoding is done via an NSData addon from this post
回答1:
To authenticate the query string you need to encode the stringToSign:
Signature = URL-Encode( Base64( HMAC-SHA1( YourSecretAccessKeyID, UTF-8-Encoding-Of( StringToSign ) ) ) );
StringToSign = HTTP-VERB + "\n" +
Content-MD5 + "\n" +
Content-Type + "\n" +
Expires + "\n" +
CanonicalizedAmzHeaders +
CanonicalizedResource;
When a browser makes the GET request, it won't provide a Content-MD5 or a Content-Type header, nor will it set any x-amz- headers, so those parts of the StringToSign are left blank.
You will need to sign the following
GET\n
\n
\n
1175139620\n
/johnsmith/photos/puppy.jpg
And the request that the browser will send is:
GET /photos/puppy.jpg?AWSAccessKeyId=AKIAIOSFODNN7EXAMPLE&
Signature=NpgCjnDzrM%2BWFzoENXmpNDUsSn8%3D&
Expires=1175139620 HTTP/1.1
Host: johnsmith.s3.amazonaws.com
Note that the Content-Type is omitted from both the request and the stringToSign, but \n remains in the stringToSign for it. The same of the rest of the optional parts.
See more examples in Authentication Examples
Check for more details in AWS Documentations
来源:https://stackoverflow.com/questions/13783749/how-to-create-pre-signed-url-in-objective-c-for-s3-without-sdk