iOS中的亚马逊产品广告API签名

我试图在我的iOS应用程序中访问亚马逊的产品广告API。 创建签名似乎是一个棘手的部分。 在本页:

http://docs.amazonwebservices.com/AWSECommerceService/latest/DG/rest-signature.html

它说“用SHA256哈希算法计算符合RFC 2104的HMAC”。 亚马逊还提供了一个java类来为你做这件事:

http://docs.amazonwebservices.com/AWSECommerceService/latest/DG/AuthJavaSampleSig2.html

有人知道我可以在Objective-C中做到这一点吗? 我查看了AWS iOS SDK,但似乎没有包含产品广告API。


实际上,AWS iOS SDK DID具有处理所有身份验证情况的静态方法。 也许你应该AmazonAuthUtils.h

+(NSString *)HMACSign:(NSData *)data withKey:(NSString *)key usingAlgorithm:(CCHmacAlgorithm)algorithm;
+(NSData *)sha256HMac:(NSData *)data withKey:(NSString *)key;

你可以在文档中找到它:http://docs.amazonwebservices.com/AWSiOSSDK/latest/Classes/AmazonAuthUtils.html


只是为了增加一点camelcc的优秀观察。 这确实适用于向亚马逊产品广告API签名请求。 为了让它工作,我不得不瞎搞。

安装SDK并使用#import <AWSiOSSDK/AmazonAuthUtils.h>

首先,您必须按照亚马逊文档的顺序将请求字符串组织成正确的顺序。 我发现这个页面在解释如何订购请求时非常有用

http://skilldrick.co.uk/2010/02/amazon-product-information-via-amazon-web-services/

注意字符串中需要换行字符,我的无符号字符串看起来像这样

@"GETnecs.amazonaws.comn/onca/xmlnAWSAccessKeyId=<ACCESS_KEY_ID>&AssociateTag=<ASSOCIATE_ID>&Keywords=harry%20potter&Operation=ItemSearch&SearchIndex=Books&Service=AWSECommerceService&Timestamp=2012-07-03T10%3A52%3A21.000Z&Version=2011-08-01"

在任何地方都没有空格,但在正确的位置放置n字符。 像这样将其转换为NSData

NSData *dataToSign = [unsignedString dataUsingEncoding:NSUTF8StringEncoding];

然后打电话

[AmazonAuthUtils HMACSign:dataToSign withKey:SECRET_KEY usingAlgorithm:kCCHmacAlgSHA256]

这会将您的签名作为NSString返回。 您需要对此网址进行网址编码(即交换%0x符号的非法/不安全文字记录器(即'='转换为'%3D'))

完成此操作后,请将其粘贴在您的要求中,并希望您能顺利出发!


查看我的亚马逊产品广告客户端https://github.com/m1entus/RWMAmazonProductAdvertisingManager

一些带有最新序列号的代码:

NSString * const RWMAmazonProductAdvertisingStandardRegion = @"webservices.amazon.com";
NSString * const RWMAmazonProductAdvertisingAWSAccessKey = @"AWSAccessKeyId";
NSString * const RWMAmazonProductAdvertisingTimestampKey = @"Timestamp";
NSString * const RWMAmazonProductAdvertisingSignatureKey = @"Signature";
NSString * const RWMAmazonProductAdvertisingVersionKey = @"Version";
NSString * const RWMAmazonProductAdvertisingCurrentVersion = @"2011-08-01";

NSData * RWMHMACSHA256EncodedDataFromStringWithKey(NSString *string, NSString *key) {
    NSData *data = [string dataUsingEncoding:NSASCIIStringEncoding];
    CCHmacContext context;
    const char *keyCString = [key cStringUsingEncoding:NSASCIIStringEncoding];

    CCHmacInit(&context, kCCHmacAlgSHA256, keyCString, strlen(keyCString));
    CCHmacUpdate(&context, [data bytes], [data length]);

    unsigned char digestRaw[CC_SHA256_DIGEST_LENGTH];
    NSUInteger digestLength = CC_SHA256_DIGEST_LENGTH;

    CCHmacFinal(&context, digestRaw);

    return [NSData dataWithBytes:digestRaw length:digestLength];
}

NSString * RWMISO8601FormatStringFromDate(NSDate *date) {
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:@"GMT"]];
    [dateFormatter setDateFormat:@"YYYY-MM-dd'T'HH:mm:ss'Z'"];
    [dateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]];

    return [dateFormatter stringFromDate:date];
}

NSString * RWMBase64EncodedStringFromData(NSData *data) {

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000
    return [data base64EncodedStringWithOptions:0];
#else
    return [data base64Encoding];
#endif

}

//http://docs.aws.amazon.com/AWSECommerceService/latest/DG/rest-signature.html

- (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request
                               withParameters:(id)parameters
                                        error:(NSError * __autoreleasing *)error
{
    NSParameterAssert(request);

    NSMutableURLRequest *mutableRequest = [request mutableCopy];

    if (self.accessKey && self.secret) {
        NSMutableDictionary *mutableParameters = [parameters mutableCopy];
        NSString *timestamp = RWMISO8601FormatStringFromDate([NSDate date]);

        if (!mutableParameters[RWMAmazonProductAdvertisingAWSAccessKey]) {
            [mutableParameters setObject:self.accessKey forKey:RWMAmazonProductAdvertisingAWSAccessKey];
        }
        mutableParameters[RWMAmazonProductAdvertisingVersionKey] = RWMAmazonProductAdvertisingCurrentVersion;
        mutableParameters[RWMAmazonProductAdvertisingTimestampKey] = timestamp;

        NSMutableArray *canonicalStringArray = [[NSMutableArray alloc] init];
        for (NSString *key in [[mutableParameters allKeys] sortedArrayUsingSelector:@selector(compare:)]) {
            id value = [mutableParameters objectForKey:key];
            [canonicalStringArray addObject:[NSString stringWithFormat:@"%@=%@", key, value]];
        }
        NSString *canonicalString = [canonicalStringArray componentsJoinedByString:@"&"];
        canonicalString = CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
                                                                                    (__bridge CFStringRef)canonicalString,
                                                                                    NULL,
                                                                                    CFSTR(":,"),
                                                                                    kCFStringEncodingUTF8));

        NSString *method = [request HTTPMethod];

        NSString *signature = [NSString stringWithFormat:@"%@n%@n%@n%@",method,self.region,self.formatPath,canonicalString];

        NSData *encodedSignatureData = RWMHMACSHA256EncodedDataFromStringWithKey(signature,self.secret);
        NSString *encodedSignatureString = RWMBase64EncodedStringFromData(encodedSignatureData);

        encodedSignatureString = CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
                                                                                           (__bridge CFStringRef)encodedSignatureString,
                                                                                           NULL,
                                                                                           CFSTR("+="),
                                                                                           kCFStringEncodingUTF8));

        canonicalString = [canonicalString stringByAppendingFormat:@"&%@=%@",RWMAmazonProductAdvertisingSignatureKey,encodedSignatureString];

        mutableRequest.URL = [NSURL URLWithString:[[mutableRequest.URL absoluteString] stringByAppendingFormat:mutableRequest.URL.query ? @"&%@" : @"?%@", canonicalString]];

    } else {
        if (error) {
            NSDictionary *userInfo = @{NSLocalizedDescriptionKey: NSLocalizedStringFromTable(@"Access Key and Secret Required", @"RWMAmazonProductAdvertisingManager", nil)};
            *error = [[NSError alloc] initWithDomain:RWMAmazonProductAdvertisingManagerErrorDomain code:NSURLErrorUserAuthenticationRequired userInfo:userInfo];
        }
    }

    return mutableRequest;

}
链接地址: http://www.djcxy.com/p/38961.html

上一篇: Amazon Product Advertising API Signature in iOS

下一篇: Amazon Product Advertising API through Java/SOAP