2012-11-04 70 views
7

我试图制作oauth_signature以使用Fatsecret API,但获取无效签名错误 - 无法找出原因。我尽可能准确地按照提及的所有步骤here(请参阅步骤2)生成签名值。他们说:签名无效:oauth_signature

使用由[RFC2104]中定义的HMAC-SHA1签名算法签署,其中文本签名基本字符串和关键是消费者的秘密和访问秘密通过分离的连接值的要求'&'字符(显示'&',即使Access Secret为空,因为某些方法不需要访问令牌)。

然后使用[RFC3986]百分比编码(%xx)机制转义计算出的摘要八位字符串,每个[RFC2045]首先进行base64编码,然后转义为oauth_signature。

对于base64编码中,我使用QSStrings.h

步骤I编码如下:

- (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",randomString, 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 = @"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; 

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

下载我的项目来查看问题

回答

6

Atlast我自己想出了代码中的错误。近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",randomString,interval]; 

在这里,我预先编码的基本字符串。当我用某种格式初始化字符串时,它以http%3A%2F%2F作为某种未知格式,用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",randomString,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",randomString, encodedString,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]; 

} 

我希望这可以帮助别人。

+0

这是您尝试使用的双腿OAuth身份验证吗?我也坚持同一个观点,无论我尝试如何正确生成签名,最终都会生成一个“无效签名”主体。我也试过你的方式,但我无法得到它。在上述方法中你有多成功? –

+0

是的。我从浏览器上面的代码测试了我生成的字符串,它工作正常。但我不知道为什么在模拟器上运行会产生签名错误。你在设备上试过这个吗? – NightFury

+0

我没有在浏览器中检查生成的字符串!我只在模拟器中测试它,因为我的开发者帐户尚未更新。那么,如果它在浏览器和设备中工作,我想它应该没问题。我将在浏览器中检查生成的URL,并让你知道什么时候回来工作。谢谢。 –