objective-c - FatSecret API“无效签名”
问题描述
使用此存储库时,我无法在oauth_token
必须提供时使查询工作。我总是得到无效的签名。在代码中尝试了很多解决方案和调整,没有任何效果。请帮忙。
这是提到的git中的代码:
NSString *OAuthorizationHeader(NSURL *url, NSString *method, NSData *body, NSString *_oAuthConsumerKey, NSString *_oAuthConsumerSecret, NSString *_oAuthToken, NSString *_oAuthTokenSecret)
{
NSString *_oAuthNonce = [NSString ab_GUID];
NSString *_oAuthTimestamp = [NSString stringWithFormat:@"%d", (int)[[NSDate date] timeIntervalSince1970]];
NSString *_oAuthSignatureMethod = @"HMAC-SHA1";
NSString *_oAuthVersion = @"1.0";
NSMutableDictionary *oAuthAuthorizationParameters = [NSMutableDictionary dictionary];
[oAuthAuthorizationParameters setObject:_oAuthNonce forKey:@"oauth_nonce"];
[oAuthAuthorizationParameters setObject:_oAuthTimestamp forKey:@"oauth_timestamp"];
[oAuthAuthorizationParameters setObject:_oAuthSignatureMethod forKey:@"oauth_signature_method"];
[oAuthAuthorizationParameters setObject:_oAuthVersion forKey:@"oauth_version"];
[oAuthAuthorizationParameters setObject:_oAuthConsumerKey forKey:@"oauth_consumer_key"];
if(_oAuthToken)
[oAuthAuthorizationParameters setObject:_oAuthToken forKey:@"oauth_token"];
// get query and body parameters
NSDictionary *additionalQueryParameters = [NSURL ab_parseURLQueryString:[url query]];
NSDictionary *additionalBodyParameters = nil;
if(body) {
NSString *string = [[NSString alloc] initWithData:body encoding:NSUTF8StringEncoding];
if(string) {
additionalBodyParameters = [NSURL ab_parseURLQueryString:string];
}
}
// combine all parameters
NSMutableDictionary *parameters = [oAuthAuthorizationParameters mutableCopy];
if(additionalQueryParameters) [parameters addEntriesFromDictionary:additionalQueryParameters];
if(additionalBodyParameters) [parameters addEntriesFromDictionary:additionalBodyParameters];
// -> UTF-8 -> RFC3986
NSMutableDictionary *encodedParameters = [NSMutableDictionary dictionary];
for(NSString *key in parameters) {
NSString *value = [parameters objectForKey:key];
[encodedParameters setObject:[value ab_RFC3986EncodedString] forKey:[key ab_RFC3986EncodedString]];
}
NSArray *sortedKeys = [[encodedParameters allKeys] sortedArrayUsingFunction:SortParameter context:(__bridge void *)(encodedParameters)];
NSMutableArray *parameterArray = [NSMutableArray array];
for(NSString *key in sortedKeys) {
[parameterArray addObject:[NSString stringWithFormat:@"%@=%@", key, [encodedParameters objectForKey:key]]];
}
NSString *normalizedParameterString = [parameterArray componentsJoinedByString:@"&"];
NSLog(@"normalizedParameters: %@", normalizedParameterString);
NSString *normalizedURLString;
if ([url port] == nil) {
normalizedURLString = [NSString stringWithFormat:@"%@://%@%@", [url scheme], [url host], [url path]];
} else {
normalizedURLString = [NSString stringWithFormat:@"%@://%@:%@%@", [url scheme], [url host], [url port], [url path]];
}
NSString *signatureBaseString = [NSString stringWithFormat:@"%@&%@&%@",
[method ab_RFC3986EncodedString],
[normalizedURLString ab_RFC3986EncodedString],
[normalizedParameterString ab_RFC3986EncodedString]];
NSLog(@"signature base: %@", signatureBaseString);
NSString *key = [NSString stringWithFormat:@"%@&%@&",
[_oAuthConsumerSecret ab_RFC3986EncodedString],
[_oAuthTokenSecret ab_RFC3986EncodedString]];
NSLog(@"key codes: %@", key);
NSData *signature = HMAC_SHA1(signatureBaseString, key);
NSString *base64Signature = [signature base64EncodedString];
// PARKER CHANGE: changed oAuthAuthorizationParameters to parameters
NSMutableDictionary *authorizationHeaderDictionary = [parameters mutableCopy];
[authorizationHeaderDictionary setObject:base64Signature forKey:@"oauth_signature"];
NSMutableArray *authorizationHeaderItems = [NSMutableArray array];
for(NSString *key in authorizationHeaderDictionary) {
NSString *value = [authorizationHeaderDictionary objectForKey:key];
NSLog(@"KEY: %@", key);
NSLog(@"VALUE: %@", value);
// PARKER CHANGE: removed quotes that surrounded each value
[authorizationHeaderItems addObject:[NSString stringWithFormat:@"%@=%@",
[key ab_RFC3986EncodedString],
[value ab_RFC3986EncodedString]]];
}
// PARKER CHANGE: changed concatentation string from ", " to "&"
NSString *authorizationHeaderString = [authorizationHeaderItems componentsJoinedByString:@"&"];
// authorizationHeaderString = [NSString stringWithFormat:@"OAuth %@", authorizationHeaderString];
NSLog(@"final: %@", authorizationHeaderString);
return authorizationHeaderString;
}
这就是我所说的:
- (void) makeUserRequestWithMethod:(NSString *)method
parameters:(NSDictionary *)params
completion:(void (^)(NSDictionary *data))completionBlock {
NSLog(@"%s", __func__);
NSMutableDictionary *parameters = [params mutableCopy];
[parameters addEntriesFromDictionary:[self defaultParameters]];
[parameters addEntriesFromDictionary:@{ @"method" : method }];
NSString *queryString = [self queryStringFromDictionary:parameters];
NSData *data = [NSData dataWithBytes:[queryString UTF8String] length:queryString.length];
NSString *authHeader = OAuthorizationHeader([NSURL URLWithString:FAT_SECRET_API_ENDPOINT],
@"POST",
data,
_oauthConsumerKey,
_oauthConsumerSecret,
_oAuthToken,
_oAuthTokenSecret
);
NSLog(@"header: %@", authHeader);
NSURL *url = [NSURL URLWithString:[FAT_SECRET_API_ENDPOINT stringByAppendingFormat:@"?%@", authHeader]];
[[[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (data) {
id JSON = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
completionBlock(JSON);
} else {
completionBlock(nil);
}
}] resume];
}
解决方案
我要在这里冒个险,说别人已经证明可以工作的代码在这里可能没有错,而是先看看你自己的代码。您说错误消息是“无效签名”,这听起来像是来自您正在调用的服务器的警告,而不是来自您正在使用的代码。
[parameters addEntriesFromDictionary:[self defaultParameters]];
[parameters addEntriesFromDictionary:@{ @"method" : method }];
NSString *queryString = [self queryStringFromDictionary:parameters];
内部发生了什么[self defaultParameters]
,您是否 100% 确定参数适合您调用的 API(包括拼写)?
您是否已验证[self queryStringFromDictionary:parameters]
准备了正确格式化的查询字符串,并且没有引入一些错误(例如,非转义的特殊字符或百分比编码)?
推荐阅读
- android - Tasks.await 错误:“不存在类型变量的实例,因此 DataReadResponse 符合 DataReadResult”
- spring - 为什么 Spring Framework 文档的目录不见了?
- android - 我应该在哪里放置一个 addValueEventListener,它只会在我的片段的 Firebase 实时数据库发生更改时触发?
- computer-vision - 是否有任何库实现在 GPU 上运行的 MSER?
- jenkins - 在 Jenkins 管道中的 shell 命令中执行时,Ansible ad-hoc 库存不起作用?
- ssl - Cloudflare 仅加密客户端和 CDN 之间的流量,但从 CDN 到服务器的连接不安全
- c++ - 通过opencv c ++沿着一条线绘制轮廓的像素值
- javascript - 如何优化弹出式 Javascript 代码?
- javascript - 如何将数据值从一个 div 克隆到另一个?
- angular - 使用 Angular 反应形式模式匹配电话号码的正则表达式