0

根据本指南,我在我的网络中配置了 2 个有腿 OAuth 服务:http: //drupal.org/node/1827698

我很确定配置是正确的,因为当我通过 Web 浏览器使用基本 URL + 服务端点触发 Web 服务时,浏览器会返回此错误:

This XML file does not appear to have any style information associated with it. The document tree is shown below.
<result>The request must be signed</result>

这确实表明这是一个身份验证错误。我想。

现在我计划在我的 iPhone 项目中使用 Restkit。我按照本指南写下了一个简单的 2 腿 OAuth 网络服务请求: https ://github.com/RestKit/RestKit/wiki/OAuth-Support-on-RestKit

这是我的代码:

    NSString *urlResource = @"";
    urlResource = @"/service_endpoint/node";
    RKObjectManager* objectManager = [RKObjectManager objectManagerWithBaseURLString:@"http://mydomain.com/"];
    [RKObjectManager setSharedManager:objectManager];
    objectManager.client.OAuth1ConsumerKey = @"proper_consumer_key";
    objectManager.client.OAuth1ConsumerSecret = @"proper_consumer_secret";
    objectManager.client.OAuth1AccessToken = nil;
    objectManager.client.OAuth1AccessTokenSecret = nil;
    objectManager.client.authenticationType = RKRequestAuthenticationTypeOAuth1;
#define USE_GET_REQUEST 0
#if USE_GET_REQUEST
    [objectManager.client get:urlResource delegate:self];
#else
    NSDictionary *theParams = nil;
    NSString *timeStamp = [[NSNumber numberWithInt:(NSTimeInterval)[[NSDate date] timeIntervalSince1970]] stringValue];
    theParams = [NSDictionary dictionaryWithObjectsAndKeys:@"1.0", @"oauth_version", @"HMAC-SHA1", @"oauth_signature_method", timeStamp, @"oauth_timestamp", nil];
    [objectManager.client post:urlResource
                        params:theParams
                      delegate:self];
#endif

如帖子中所示,我之前尝试过使用 GET 请求。我得到一个没有任何数据的空正文,并且 Restkit 在某处记录了此内容,这表明存在授权问题:

2012-11-06 19:27:46.887 MyProject OAuth[22187:11603] 我 restkit.network:RKRequest.m:689 状态码:401

我意识到 Restkit 不会以这种方式添加任何参数,因此请求不知道要使用什么签名、时间戳和 OAuth 版本。因此,我使用可以指定这些参数的 POST 请求尝试了相同的操作。即使现在我得到一个空的身体和 Restkit 日志这样说:

2012-11-06 19:28:03.231 MyProject OAuth[22205:11603] I restkit.network:RKRequest.m:689 状态码:404

我不知道我哪里出错了或者还有什么可以尝试的!期待帮助解决此问题。

编辑: 我实现了一个缺少的回调方法,现在得到:

“请求必须签名”

信息。我认为上述设置对于 OAuth 身份验证应该已经足够了,如引用的链接中所述,我还应该做什么?

观察

我可以看到 RestKit 代码的内部结构,并且 OAuth 参数被放入 URL 请求的 HTTP 标头字段中。但我不确定 Drupal 7 是否能够从 HTTP 标头字段中读取此信息,因为它总是返回给我:

请求必须签名

这意味着在第一种情况下 Drupal 没有收到 OAuth 参数,否则它至少会给我以下错误:

无效签名

我正在寻找其他一些选项,以查看我的使用者密钥和秘密以及所有其他设置是否在服务器端正确完成。为了确认这一点,我从这里下载了 php OAuth 客户端脚本。从这里下载 SVN 代码。当我使用 PHP 客户端交叉检查请求时,我的请求都得到了完美的服务,我只需输入端点、消费者密钥和消费者密码就可以取回 xml。

我尝试的另一件事是允许 GCOAuth 在 Restkit 中生成签名和所有内容并放置一个断点,以便我可以将 HTTP 标头字段转储到日志中,而不是 Restkit 将请求发送到服务器,我快速准备了 URL请求格式与上述 PHP 客户端完全相同。现在这个请求被触发时,我得到了

无效签名

响应,这是否也意味着在 Restkit / GCOAuth 中未正确准备 OAuth 参数?

谢谢,拉吉

4

1 回答 1

0

我能够通过更改 Restkit 的类来解决它。根据我在上面问题中提到的观察,我能够弄清楚我认为是某些网络服务器的限制,在这种情况下可以说是 Drupal 7。几乎在我遇到的所有 iOS 的 OAuth 库中,OAuth 身份验证参数都是在请求的 HTTP 标头字段中设置的。

我遇到了PHP 客户端(如我在上面的观察中提到的),如果我们提供正确的消费者密钥和消费者秘密,它将生成 oauth_nonce 字符串、时间戳,并且还将在 URL 的查询参数中提供 oauth_signature。Restkit 的库中缺少此功能(我假设?)。尽管 Restkit 用 GCOAuth 提供的所有信息填充了 HTTP 标头字段,但我觉得我的 Drupal 7 网络服务器没有以某种方式读取它,或者我可能为 HTTP 标头字段使用了错误的键。我搜索了 Drupal 7 关于如何在 HTTP 标头字段中传递参数并从那里读取的文档,但我找不到太多帮助,而且我也不是很精通。

所以我的解决方案是像上面提到的PHP 客户端那样构建 URL 请求。几乎所有的事情都是由 Restkit 在 GCOAuth 类、RKClient 和 RKRequest 类中完成的。我所要做的就是进行调整,以便将 OAuth 参数附加到请求 URL。我已将所有更改推送到github 中的 Restkit 分叉代码。我对此 OAuth 模块的特定更改用“// Raj OAuth:”注释,可以在项目中搜索。

下面是我成功用来触发和使用 web 服务的代码。目前我已经为 RKClient 的-get:delegate:方法提供了一个重载的指定方法,我相信同样可以根据需要扩展到所有其他可用的方法。

-(void)triggerOAuthRequest
{
    NSString *urlResource = @"";
    urlResource = @"/endpoint_path/endpoint.xml";
    NSString *baseURL = @"http://your_domain_name.com/path_to_drupal_home_folder/";
    NSString *consumerKey = @"YW9h6tUc*************";
    NSString *consumerSecret = @"HUS2ALAC*************";

    RKObjectManager* objectManager = [RKObjectManager objectManagerWithBaseURLString:baseURL];
    [RKObjectManager setSharedManager:objectManager];
    objectManager.client.OAuth1ConsumerKey = consumerKey;
    objectManager.client.OAuth1ConsumerSecret = consumerSecret;
    objectManager.client.OAuth1AccessToken = nil;
    objectManager.client.OAuth1AccessTokenSecret = nil;
    objectManager.client.authenticationType = RKRequestAuthenticationTypeOAuth1;
    [objectManager.client get:urlResource
                     delegate:self
constructOAuthQueryParamsInURL:YES];
}

我还假设发送此请求足够安全,因为我的 OAuth 参数在客户端使用秘密消费者密钥进行签名,然后请求被发送到服务器,尽管 URL 本身具有查询参数,但我觉得这是安全的,因为 oauth_signature 使用秘密消费者密钥进行签名,只有网络服务器可以解密并检查请求是否来自真实来源。

如果您觉得有任何改进的余地,请告诉我。

谢谢,

拉吉

于 2012-11-09T05:46:17.660 回答