2

我正在构建一个 mac 应用程序,而不是使用 AWS iOS 开发工具包。我正在尝试构建的 GET 请求应遵循以下一般格式:

"Authorization: AWS " + AWSAccessKeyId + ":" + base64(hmac-sha1(VERB + "\n" + CONTENT-MD5 + "\n" + CONTENT-TYPE + "\n" + DATE + "\n" + CanonicalizedAmzHeaders + "\n" + CanonicalizedResource))

在Amazon docs中作为“伪语法”提供。我一直在寻找澄清,似乎根据很多人的说法,base64 哈希中的许多字段都是可选的。

以下是我到目前为止的想法。但是我得到的响应是来自 AWS 的错误,说“不支持的授权类型”引用了标题中的“授权”字段。我在这里真的很难过。有关如何调试或修复此问题的任何见解?

有没有其他方法可以在 Obj C 中为 S3 生成预​​签名的 url?

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

base64 编码是通过这篇文章中的 NSData 插件完成的

4

1 回答 1

0

要验证查询字符串,您需要对 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;

当浏览器发出 GET 请求时,它不会提供 Content-MD5 或 Content-Type 标头,也不会设置任何 x-amz- 标头,因此 StringToSign 的那些部分留空。

您将需要签署以下文件

GET\n
\n
\n
1175139620\n

/johnsmith/photos/puppy.jpg

浏览器将发送的请求是:

GET /photos/puppy.jpg?AWSAccessKeyId=AKIAIOSFODNN7EXAMPLE&
    Signature=NpgCjnDzrM%2BWFzoENXmpNDUsSn8%3D&
    Expires=1175139620 HTTP/1.1

Host: johnsmith.s3.amazonaws.com

请注意,请求和 stringToSign 都省略了 Content-Type,但\n仍保留在 stringToSign 中。其余可选部分相同。

在身份验证示例中查看更多示例

在AWS 文档中查看更多详细信息

于 2012-12-09T11:22:10.407 回答