在受OAuth保护的URL上进行GET调用,第2部分

时间:2012-06-19 03:17:57

标签: objective-c ios oauth

我一直试图让基本的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中遇到了一些细微差别。提前谢谢。

4 个答案:

答案 0 :(得分:4)

如果我是你,我会查看ShareKitgithub的源代码,该代码与许多OAuth网络服务集成。我相信它使用了OAuthConsumer,这对你来说可能特别有用。 OAuthConsumer有一些文档,您可能想尝试将它集成到您​​的应用程序中。

如果您查看OAMutableURLRequest,可以看到OAuthConsumer如何创建请求。我没有看到标头设置方式有任何重大差异,只是它们有一个realm标头。我的建议是尝试使用OAuthConsumer来发出请求并查看它是否有效。如果它不能与OAuthConsumer一起使用,那么我会想象问题出现在其他地方(可能在服务器上?)。

答案 1 :(得分:1)

我玩过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版本。)

如果您需要进一步澄清,我很乐意编辑您的评论的问题或答案。

奖励!

答案 2 :(得分:1)

我遇到了一个问题,包括标题字段,所以我通过将所有参数包含在url编码中来摆脱它们。我做了以下。

  • 使用OAuthConsumer-iphone twitter app http://code.google.com/p/oauthconsumer-iphone/
  • 转到 - (void)在OADataFetcher.m下准备,通过执行[request setParameters:[(NSArray *)allParameters urlEncoded]]来摆脱oauthheader并将所有参数包含为url参数;
  • 休息应该很简单。
  • 总而言之,您将集中注意的所有文件都是oauthTwitterAppViewController,OAMutableURLRequest,OADataFetcher,AuthorizeWebViewController。

我花了将近一周的时间与服务提供商进行同步才能实现这一目标。但是如果你准备好了所有的资源,那么可能你可能需要2天。

答案 3 :(得分:0)

我看到了你的代码,在看了这个网站上的其他一些问题后,我终于构建了一个正在运行的代码。 在我的例子中,我使用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));}