2012-11-04 15 views
7

oauth_signatureを使用してFatsecret APIを生成しようとしていますが、無効な署名エラーが発生しました。私はhere(ステップ2を参照)に記載されているすべてのステップを実行して、署名値の生成を可能な限り正確に行いました。彼らは言う:[RFC2104]で定義されるように無効な署名:oauth_signature

テキストは、署名ベース文字列であり、キーにより分離コンシューマシークレットとアクセスシークレットの連結された値である要求に署名するためにHMAC-SHA1署名アルゴリズムを使用し'&'文字(一部の方法でアクセストークンが必要ないため、Access Secretが空の場合でも '&'を表示)

最初に[RFC2045]に従ってbase64でエンコードされ、[RFC3986]パーセントエンコーディング(%xx)メカニズムを使用してエスケープされた計算ダイジェストオクテット文字列は、oauth_signatureです。 base64エンコーディングについて

、Iは以下の通りであるI符号化QSStrings.h

手順を使用:

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

を次のように私は上記のコードで使用されるメソッドの

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

} 

定義はあなたは私のプロジェクトをダウンロードすることで問題を見ることができますhere

答えて

6

アトラス私は自分でコードの間違いを理解しました。ほぼ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]; 

ここでIプリエンコードされたベース文字列。私は何らかのフォーマットで文字列を初期化するので、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

これは試していた2足のOAuth認証ですか?私は同じポイントで立ち往生しています。どれだけ署名を正しく作成しようとしても、「無効な署名」のボディになります。私もあなたのやり方を試しましたが、私はそれを得ることができませんでした。あなたは上記のアプローチでどれくらい成功しましたか? –

+0

はいです。私は上記のコードからブラウザ上で私の生成された文字列をテストし、それは正常に動作しています。しかし、私はなぜシミュレータ上で実行すると署名エラーが発生するのか分かりません。あなたはこれをデバイスで試しましたか? – NightFury

+0

私はhaventブラウザで生成された文字列をチェック!開発者アカウントがまだ更新されていないので、シミュレータでのみテストしています。まあ、それがブラウザやデバイスで動作する場合、私はそれがうまくいくはずだと思います。私はブラウザで生成されたURLをチェックし、いつ仕事から戻ってくるかを知らせます。ありがとう。 –