【发布时间】:2017-04-28 08:43:14
【问题描述】:
我一直在寻找可以为 Oauth 标头生成签名的代码,这让我很痛苦。我的目标平台是 iOS,我需要为 TradeKing API 执行此操作。基本上他们的查询需要 OAuth(无需使用 Oauth 工作流程提前授权我的应用程序供个人使用;我只需要使用 TradeKing 提供给我的密钥使用 oauth 标头对每个查询进行签名)。这是一些示例文档:GetPost
我发现的最佳示例代码如下:https://github.com/Christian-Hansen/simple-oauth1
我能够按照他的示例显示 LinkedIn 库登录。然后我修改了 TradeKing REST 查询的代码,但由于签名无效而失败。这让我很担心,因为生成签名的代码是最复杂的部分……而且我不确定我是否正确使用了他的代码。在下面的代码中,我将 oauth 密钥和秘密更改为 Xs。
/* THE URL REQUEST */
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://api.tradeking.com/v1/market/ext/quotes.xml?symbols=aapl"]];
request.HTTPMethod = @"GET";
/* OAUTH FIELDS */
NSString *oauth_timestamp = [NSString stringWithFormat:@"%lu", (unsigned long)[NSDate.date timeIntervalSince1970]];
NSString *oauth_nonce = [NSString getNonce];
NSString *oauth_consumer_key = @"xxxxxxx";
NSString *oauth_token = @"xxxxxxx";
NSString *oauth_signature_method = @"HMAC-SHA1";
NSString *oauth_version = @"1.0";
NSMutableDictionary *standardParameters = [NSMutableDictionary dictionary];
[standardParameters setValue:oauth_consumer_key forKey:@"oauth_consumer_key"];
[standardParameters setValue:oauth_nonce forKey:@"oauth_nonce"];
[standardParameters setValue:oauth_signature_method forKey:@"oauth_signature_method"];
[standardParameters setValue:oauth_timestamp forKey:@"oauth_timestamp"];
[standardParameters setValue:oauth_version forKey:@"oauth_version"];
[standardParameters setValue:oauth_token forKey:@"oauth_token"];
NSString *parametersString = CHQueryStringFromParametersWithEncoding(standardParameters, NSUTF8StringEncoding);
/* OAUTH SIGNATURE */
NSString *request_url = @"https://api.tradeking.com/v1/market/ext/quotes.xml?symbols=aapl";
NSString *oauth_consumer_secret = @"xxxxxx";
NSString *oauth_token_secret = @"xxxx";
NSString *baseString = [@"GET" stringByAppendingFormat:@"&%@&%@", request_url.utf8AndURLEncode, parametersString.utf8AndURLEncode];
// append oauth token secret to consumer secret
NSString *secretString = [oauth_consumer_secret.utf8AndURLEncode stringByAppendingFormat:@"&%@", oauth_token_secret.utf8AndURLEncode];
NSString *oauth_signature = [self.class signClearText:baseString withSecret:secretString];
standardParameters[@"oauth_signature"] = oauth_signature;
/* CREATE HEADER */
NSMutableArray *parameterPairs = [NSMutableArray array];
for (NSString *name in standardParameters)
{
NSString *aPair = [name stringByAppendingFormat:@"=\"%@\"", [standardParameters[name] utf8AndURLEncode]];
[parameterPairs addObject:aPair];
}
NSString *oAuthHeader = [@"OAuth " stringByAppendingFormat:@"%@", [parameterPairs componentsJoinedByString:@", "]];
[request setValue:oAuthHeader forHTTPHeaderField:@"Authorization"];
/* REQUEST */
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
NSString *reponseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"Response string: %@, error: %@", reponseString, error);
}];
我得到的回复是“signature_invalid”。无论如何,我省略了与 url 编码和签名生成相关的部分,因为它们可能会占用太多空间。我想知道我是否在这里犯了错误,或者创建签名的实际函数是否有问题。
【问题讨论】:
-
CHQueryStringFromParametersWithEncoding是否确保参数按字母顺序排列? -
好点斯蒂芬......这里是:打印参数描述字符串:oauth_consumer_key=xxxx&oauth_nonce=xxxx&oauth_signature_method=HMAC-SHA1&oauth_timestamp=xxxx&oauth_token=xxxxx8&oauth_version=1.0 所以是的,它按字母顺序排序。我什至现在在那个函数中手动对它们进行排序,我得到了同样的错误