FatSecret API "неверная подпись" - PullRequest
0 голосов
/ 27 апреля 2018

Использование этого репозитория Мне не удалось заставить запросы работать, когда необходимо указать 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];
}

1 Ответ

0 голосов
/ 08 мая 2018

Я собираюсь пойти дальше и сказать, что код, который доказали другие, вероятно, здесь не виноват, а скорее сначала посмотрит на ваш собственный код. Вы говорите, что сообщения об ошибке «Недействительная подпись», что звучит как предупреждение от сервера, которому вы звоните, а не от кода, который вы используете.

[parameters addEntriesFromDictionary:[self defaultParameters]];
[parameters addEntriesFromDictionary:@{ @"method" : method }];

NSString *queryString = [self queryStringFromDictionary:parameters];

Что происходит внутри [self defaultParameters] и уверены ли вы на 100%, что параметры соответствуют (включая орфографию) API-интерфейсу, который вы вызываете?

Проверено ли, что [self queryStringFromDictionary:parameters] готовит правильно отформатированную строку запроса и не вносит какую-либо ошибку (например, не экранированные специальные символы или процентное кодирование)?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...