【问题标题】:Making a GET call on an OAuth protected URL, part 2对受 OAuth 保护的 URL 进行 GET 调用,第 2 部分
【发布时间】:2012-06-21 01:51:21
【问题描述】:

我一直在尝试让基本的 OAuth 交互正常工作,但没有成功。当然,在 SO 上已经提出了类似的问题,但大多数都没有答复。我在这里变得非常绝望,所以我将首先发布我的整个代码:

// OAuth parameters
NSString *oauthNonce = [self genRandStringLength:20];
NSString *oauthSignatureMethod = [NSString stringWithFormat:@"HMAC-SHA1"];
time_t oauthTimeStamp = (time_t) [[NSDate date] timeIntervalSince1970];

// generate OAuth signature
NSString *encodedUrlString = [self urlEncode:urlString];

NSString *oauthParameters = [NSString stringWithFormat:@"oauth_consumer_key=%@",oauthConsumerKey];
oauthParameters = [oauthParameters stringByAppendingFormat:@"&oauth_nonce=%@",oauthNonce];
oauthParameters = [oauthParameters stringByAppendingFormat:@"&oauth_signature_method=%@",oauthSignatureMethod];
oauthParameters = [oauthParameters stringByAppendingFormat:@"&oauth_timestamp=%d",oauthTimeStamp];
oauthParameters = [oauthParameters stringByAppendingFormat:@"&oauth_token=%@",oauthAccessToken];
oauthParameters = [oauthParameters stringByAppendingFormat:@"&oauth_version=1.0"];
NSString *oauthEncodedParameters = [self urlEncode:oauthParameters];

NSString *oauthBaseString = [NSString stringWithFormat:@"GET&%@&%@",encodedUrlString,oauthEncodedParameters];

NSString *oauthKey = [NSString stringWithFormat:@"%@&%@", oauthConsumerSecret, oauthAccessTokenSecret];
NSString *oauthEncodedKey = [self urlEncode:oauthKey];

OAHMAC_SHA1SignatureProvider *provider = [[OAHMAC_SHA1SignatureProvider alloc] init];
NSString *oauthSignature = [provider signClearText:oauthBaseString withSecret:oauthEncodedKey];
NSString *oauthEncodedSignature = [self urlEncode:oauthSignature];

// prepare request
NSString *oauthHeader = @"OAuth ";
oauthHeader = [oauthHeader stringByAppendingFormat:@"oauth_consumer_key=\"%@\"",oauthConsumerKey];
oauthHeader = [oauthHeader stringByAppendingFormat:@",oauth_token=\"%@\"",oauthAccessToken];
oauthHeader = [oauthHeader stringByAppendingFormat:@",oauth_signature_method=\"%@\"",oauthSignatureMethod];
oauthHeader = [oauthHeader stringByAppendingFormat:@",oauth_signature=\"%@\"",oauthEncodedSignature];
oauthHeader = [oauthHeader stringByAppendingFormat:@",oauth_timestamp=\"%d\"",oauthTimeStamp];
oauthHeader = [oauthHeader stringByAppendingFormat:@",oauth_nonce=\"%@\"",oauthNonce];
oauthHeader = [oauthHeader stringByAppendingFormat:@",oauth_version=\"1.0\""];

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlString]];
[request setHTTPMethod:@"GET"];
[request setValue:oauthHeader forHTTPHeaderField:@"Authorization"];

NSHTTPURLResponse *response = nil;
NSError *error = nil;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];

当我查看 http 响应代码时,我得到了 500。我已就意外的 500 响应联系了服务提供商。

与此同时,我可能做错了什么?

即使只是向我指出一些工作示例代码,我也将不胜感激。我已经阅读了很多东西,但我显然在 obj-c 中弄错了一些细微差别。提前致谢。

【问题讨论】:

    标签: objective-c ios oauth


    【解决方案1】:

    我看到了你的代码,在这个网站上看了一些其他问题之后,我终于构建了一个运行代码。 在我的例子中,我使用 AFHTTPClient 发起请求,我只使用 OAMutableURLRequest 创建 Authorization 标头,然后我使用 Authorization 标头附加到我发送到服务器的请求。

    我在这里将我的代码分享给需要它的人。

    在您的情况下,我认为您应该检查发送到服务器的请求,并使用 Fiddler 编写测试请求来调试您的服务。

    对不起我的英语不好:p.

    NSDictionary * jsonDic;
    __block NSString *responsebody = @"";
    OAConsumer *consumer = [[OAConsumer alloc] initWithKey:@"123"
                                                    secret:@"456"];
    NSURL *url = [NSURL URLWithString:@"http://MyServiceURL/MyServiceFunction"];
    
    OAMutableURLRequest *request = [[OAMutableURLRequest alloc] initWithURL:url
                                                                   consumer:consumer
                                                                      token:nil
                                                                      realm:nil
                                                          signatureProvider:nil];
    [request prepare];
    
    NSString *oauthHeader = @"OAuth ";
    oauthHeader = [oauthHeader stringByAppendingFormat:@"oauth_consumer_key=\"%@\"",@"123"];
    oauthHeader = [oauthHeader stringByAppendingFormat:@",oauth_token=\"%@\"",@""];
    oauthHeader = [oauthHeader stringByAppendingFormat:@",oauth_signature_method=\"%@\"",@"HMAC-SHA1"];
    oauthHeader = [oauthHeader stringByAppendingFormat:@",oauth_signature=\"%@\"",encodeToPercentEscapeString(request.signature)];
    oauthHeader = [oauthHeader stringByAppendingFormat:@",oauth_timestamp=\"%ld\"", (time_t) [[NSDate date] timeIntervalSince1970]];
    oauthHeader = [oauthHeader stringByAppendingFormat:@",oauth_nonce=\"%@\"",request.nonce];
    oauthHeader = [oauthHeader stringByAppendingFormat:@",oauth_version=\"1.0\""];
    //NSLog(@"oauthHeader: %@", oauthHeader);
    
    [AFNetworkActivityIndicatorManager sharedManager].enabled = YES;
    
    NSURL *baseURL = [NSURL URLWithString:@"http://MyServiceURL"];
    AFHTTPClient* client = [[AFHTTPClient alloc] initWithBaseURL:baseURL];
    [client setParameterEncoding:AFJSONParameterEncoding];
    [client setDefaultHeader:@"Accept" value:RKMIMETypeJSON];
    [client setDefaultHeader:@"Content-Type" value:@"application/json"];
    [client setDefaultHeader:@"Authorization" value:oauthHeader];
    
    NSDictionary *finalDict = @{@"user":@{@"id":@"001"}};
    // create a JSON string from your NSDictionary
    NSError *error;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:finalDict options:NSJSONWritingPrettyPrinted error:&error];
    
    [client postPath:@"/MyServiceFunction"
          parameters:finalDict
             success:^(AFHTTPRequestOperation  *operation, id JSON) {
                 responsebody = operation.responseString;
                 jsonDic = [NSJSONSerialization JSONObjectWithData:[responsebody dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableLeaves error:nil];
             }
             failure:^(AFHTTPRequestOperation  *operation, NSError *error) {
                 NSLog(@"Hit error: %@", error);
             }];
    

    NSString* encodeToPercentEscapeString(NSString *string) {
    return (NSString *)
    CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(NULL,
                                            (CFStringRef) string,
                                            NULL,
                                            (CFStringRef) @"!*'();:@&=+$,/?%#[]",
                                            kCFStringEncodingUTF8));}
    

    【讨论】:

      【解决方案2】:

      我遇到了包含标头字段的问题,因此我通过将所有参数包含为 url 编码来摆脱它们。我做了以下。

      • 使用 OAuthConsumer-iphone twitter 应用 http://code.google.com/p/oauthconsumer-iphone/
      • 转到 -(void)prepare 在 OADataFetcher.m 下,摆脱 oauthheader 并通过执行 [request setParameters:[(NSArray *)allParameters urlEncoded]] 将所有参数包含为 url 参数;
      • 休息应该是直截了当的。
      • 因此,您将关注的所有文件总共是 oauthTwitterAppViewController、OAMutableURLRequest、OADataFetcher、AuthorizeWebViewController。

      我花了将近一个星期的时间与服务提供商同步以使其正常工作。但是,如果您准备好所有资源,那么您可能需要 2 天时间。

      【讨论】:

        【解决方案3】:

        如果我是你,我会在 github 上查看 ShareKit 的源代码,它与许多 OAuth Web 服务集成。我相信它使用OAuthConsumer,这可能对您特别有用。 OAuthConsumer 有一些文档,您可能想尝试将其集成到您的应用程序中。

        如果您查看OAMutableURLRequest,您可以看到 OAuthConsumer 如何创建请求。除了它们有一个realm 标头之外,我看不到您的标头设置方式有任何重大差异。我的建议是尝试使用 OAuthConsumer 发出请求,看看它是否有效。如果它不适用于 OAuthConsumer,那么我会认为问题出在其他地方(可能在服务器上?)。

        【讨论】:

        • 我与哪个 Web 服务交互并不重要,对吗?我只是试图检索 (GET) 受 OAuth 保护的 URL,因此我试图签署请求。如果我完全误解了 OAuth,请告诉我。感谢您的回复。
        • 不,一般来说,与您交互的 oauth 服务无关紧要。我用新链接更新了我的答案。
        • 我最终使用了 jdg 的 OAuthConsumer 版本 (github.com/jdg/oauthconsumer),这让我得到了我需要的东西。我会把你的答案标记为正确的,恭喜!
        • 很高兴能帮到你,别忘了奖励赏金
        • 没有意识到除了标记正确答案之外,我还必须奖励赏金!关闭一个.. :)
        【解决方案4】:

        我已经有一段时间没有使用 OAuth 了,但我已经为 PHP 和 Objective-C 制作了一个小项目,让我不再需要再弄乱它了。

        我的猜测是您的标题字段需要按字段名称排序,因此,顺序应该是这样的:

        NSString *oauthHeader = @"OAuth ";
        oauthHeader = [oauthHeader stringByAppendingFormat:@"oauth_consumer_key=\"%@\"",oauthConsumerKey];
        oauthHeader = [oauthHeader stringByAppendingFormat:@",oauth_nonce=\"%@\"",oauthNonce];
        oauthHeader = [oauthHeader stringByAppendingFormat:@",oauth_timestamp=\"%d\"",oauthTimeStamp];
        oauthHeader = [oauthHeader stringByAppendingFormat:@",oauth_token=\"%@\"",oauthAccessToken];
        oauthHeader = [oauthHeader stringByAppendingFormat:@",oauth_signature=\"%@\"",oauthEncodedSignature];
        oauthHeader = [oauthHeader stringByAppendingFormat:@",oauth_signature_method=\"%@\"",oauthSignatureMethod];
        oauthHeader = [oauthHeader stringByAppendingFormat:@",oauth_version=\"1.0\""];
        

        请随时查看我在 Gitorious for Objective-C 中的 uOAuth (micro-OAuth) project 源代码(如果您也想查看的话,还有一个 PHP 版本)。

        如果您需要更多说明,我很乐意编辑问题或回答您的评论。

        赞!

        【讨论】:

        • 谢谢,等我回来试试。根据您的“按字段名称排序”,不应该将oauth_timestampoauth_token 放在oauth_signatureoauth_signature_method 下方吗?感谢您的回复。
        • 我都试过了(你的订购和我上面评论中的订购),但都失败了。
        猜你喜欢
        • 1970-01-01
        • 2021-10-29
        • 1970-01-01
        • 2012-11-16
        • 2011-01-23
        • 2019-01-14
        • 2012-03-30
        • 1970-01-01
        • 2014-02-11
        相关资源
        最近更新 更多