我正在尝试生成oauth_signature以使用Fatsecret API,但是获得无效的签名错误 – 无法弄清楚原因.我尝试尽可能准确地遵循
here所述的所有步骤(参见步骤2)来生成签名值.他们说:
Use the HMAC-SHA1 signature algorithm as defined by the [RFC2104] to sign the request where text is the Signature Base String and key is the concatenated values of the Consumer Secret and Access Secret separated by an ‘&’ character (show ‘&’ even if Access Secret is empty as some methods do not require an Access Token).
The calculated digest octet string,first base64-encoded per [RFC2045],then escaped using the [RFC3986] percent-encoding (%xx) mechanism is the oauth_signature.
对于base64编码,我使用了QSStrings.h
我编码的步骤如下:
- (void)viewDidLoad { NSTimeInterval intervalFloat = [[NSDate date] timeIntervalSince1970]; int interval = (int) intervalFloat; NSLog(@"time interval: %d",interval); //for oauth_nonce random string Nsstring *randomString = [self genRandString]; //see deFinition below NSLog(@"%@",randomString); Nsstring *requestString = [Nsstring stringWithFormat:@"POST&http%3A%2F%2Fplatform.fatsecret.com%2Frest%2Fserver.api&format%3Djson%26method%3Dprofile.create%26oauth_consumer_key%3Db753c99ccxxxxxx%26oauth_nonce%3D%@%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D%d%26oauth_version%3D1.0",randomString,interval]; Nsstring *secret = @"3959096c04xxxxxxxx&"; Nsstring *encodedStr = [self hmacsha1:requestString secret:secret]; //see deFinition below NSLog(@"encodedStr: %@",encodedStr); Nsstring *encodedString = [self urlEncodeValue:encodedStr]; //see deFinition below NSLog(@"encodedString: %@",encodedString); NSURL *url = [NSURL URLWithString:[Nsstring stringWithFormat:@"http://platform.fatsecret.com/rest/server.api?format=json&method=profile.create&oauth_consumer_key=b753c99ccxxxxxx&oauth_nonce=%@&oauth_signature=%@&oauth_signature_method=HMAC-SHA1&oauth_timestamp=%d&oauth_version=1.0",encodedString,interval]]; _request = [ASIFormDataRequest requestWithURL:url]; [_request setPostValue:@"json" forKey:@"format"]; [_request setPostValue:@"profile.create" forKey:@"method"]; [_request setPostValue:@"b753c99ccxxxxxx" forKey:@"oauth_consumer_key"]; [_request setPostValue:randomString forKey:@"oauth_nonce"]; [_request setPostValue:encodedString forKey:@"oauth_signature"]; [_request setPostValue:@"HMAC-SHA1" forKey:@"oauth_signature_method"]; [_request setPostValue:[NSNumber numberWithInt:interval] forKey:@"oauth_timestamp"]; [_request setPostValue:@"1.0" forKey:@"oauth_version"]; [_request setDelegate:self]; _request.timeOutSeconds = 60.0; [_request startAsynchronous]; }
我在上面的代码中使用的方法的定义如下:
- (Nsstring *)hmacsha1:(Nsstring *)data secret:(Nsstring *)key { const char *cKey = [key cStringUsingEncoding:NSASCIIStringEncoding]; const char *cData = [data cStringUsingEncoding:NSASCIIStringEncoding]; unsigned char cHMAC[CC_SHA1_DIGEST_LENGTH]; CCHmac(kCCHmacAlgSHA1,cKey,strlen(cKey),cData,strlen(cData),cHMAC); NSData *HMAC = [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)]; Nsstring *hash = [Qsstrings encodeBase64WithData:HMAC]; NSLog(@"Hash: %@",hash); return hash; } Nsstring *letters = @"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMnopQRSTUVWXYZ0123456789"; -(Nsstring *) genRandString { //fixing length of 4 chars NSMutableString *randomString = [NSMutableString stringWithCapacity: 4]; for (int i=0; i<4; i++) { [randomString appendFormat: @"%C",[letters characteratIndex: arc4random() % [letters length]]]; } return randomString; } - (Nsstring *)urlEncodeValue:(Nsstring *)str { NSMutableString * output = [NSMutableString string]; const unsigned char * source = (const unsigned char *)[str UTF8String]; int sourceLen = strlen((const char *)source); for (int i = 0; i < sourceLen; ++i) { const unsigned char thisChar = source[i]; if (thisChar == ' '){ [output appendString:@"+"]; } else if (thisChar == '.' || thisChar == '-' || thisChar == '_' || thisChar == '~' || (thisChar >= 'a' && thisChar <= 'z') || (thisChar >= 'A' && thisChar <= 'Z') || (thisChar >= '0' && thisChar <= '9')) { [output appendFormat:@"%c",thisChar]; } else { [output appendFormat:@"%%%02X",thisChar]; } } return output; }
您可以通过从here下载我的项目来查看问题
解决方法
我自己找到了代码中的错误.近80%的问题已经解决.我在这个地方做错了:
Nsstring *requestString = [Nsstring stringWithFormat:@"POST&http%3A%2F%2Fplatform.fatsecret.com%2Frest%2Fserver.api&format%3Djson%26method%3Dprofile.create%26oauth_consumer_key%3Db753c99ccxxxxxx%26oauth_nonce%3D%@%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D%d%26oauth_version%3D1.0",interval];
这里我预先编码了基本字符串.当我使用某种格式初始化字符串时,它将http://视为某种未知格式,将其替换为0.所以我将整个代码替换为:
- (void)viewDidLoad { [super viewDidLoad]; //for timestamp NSTimeInterval intervalFloat = [[NSDate date] timeIntervalSince1970]; int interval = (int) intervalFloat; NSLog(@"time interval: %d",interval); //for oauth_nonce random string Nsstring *randomString = [self genRandString]; NSLog(@"%@",randomString); Nsstring *actualString = [Nsstring stringWithFormat:@"format=json&method=profile.create&oauth_consumer_key=b753c99ccd8****&oauth_nonce=%@&oauth_signature_method=HMAC-SHA1&oauth_timestamp=%d&oauth_version=1.0",interval]; Nsstring *firstEncode = [self urlEncodeValue:actualString]; NSLog(@"first encode: %@",firstEncode); NSMutableString *requestString = [[NSMutableString alloc] initWithString:@"GET&http%3A%2F%2Fplatform.fatsecret.com%2Frest%2Fserver.api&"]; [requestString appendString:firstEncode]; NSLog(@"base str: %@",requestString); Nsstring *secret = @"395********&"; Nsstring *encodedStr = [self hmacsha1:requestString secret:secret]; NSLog(@"encodedStr: %@",encodedStr); Nsstring *encodedString = [self urlEncodeValue:encodedStr]; NSLog(@"encodedString: %@",encodedString); NSURL *url = [NSURL URLWithString:[Nsstring stringWithFormat:@"http://platform.fatsecret.com/rest/server.api?format=json&method=profile.create&oauth_consumer_key=b753c99cc*******&oauth_nonce=%@&oauth_signature=%@&oauth_signature_method=HMAC-SHA1&oauth_timestamp=%d&oauth_version=1.0",interval]]; NSLog(@"url: %@",url); _request = [ASIFormDataRequest requestWithURL:url]; [_request setPostValue:@"json" forKey:@"format"]; [_request setPostValue:@"profile.create" forKey:@"method"]; [_request setPostValue:@"b753c9*********" forKey:@"oauth_consumer_key"]; [_request setPostValue:randomString forKey:@"oauth_nonce"]; [_request setPostValue:encodedString forKey:@"oauth_signature"]; [_request setPostValue:@"HMAC-SHA1" forKey:@"oauth_signature_method"]; [_request setPostValue:[NSNumber numberWithInt:interval] forKey:@"oauth_timestamp"]; [_request setPostValue:@"1.0" forKey:@"oauth_version"]; [_request setRequestMethod:@"GET"]; [_request addRequestHeader:@"Content-Type" value:@"application/json"]; [_request setDelegate:self]; _request.timeOutSeconds = 60.0; [_request startAsynchronous]; }
我希望这可以帮助别人.