2012-11-04 95 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,並讓你知道什麼時候回來工作。謝謝。 –