【问题标题】:Restkit 0.20 basic operationRestkit 0.20 基本操作
【发布时间】:2013-02-06 20:15:11
【问题描述】:

我刚刚开始使用 RestKit,并且在 Rk 0.20 即将上线并且文档和演示落后了一步。网络上的大多数东西都是针对 RK 0.10 的,0.20 版本有很大的变化。

当新版本很快就会启动并运行时,我不想退回到早期版本。

我在 URL“test.myserver.com”上有一个 JSON 资源,它返回一个简单的数据报 - { “id_user”:“4401”, “数据位置”:“4401”, “国家”:“英国”, “数据”:“测试数据”, “登录”:“弗雷德博客”, “密码”:“579c0cb0ed2dc25db121283f7a98cc71”, “访问级别”:“2”, “时间戳”:“1012”, “数据哈希”:“2749da29f20ce7a85092323f193adee8” }

我很确定我已经对映射等进行了排序,但我的服务需要身份验证,所以我需要在请求中将用户名和密码传递给服务器。

到目前为止我已经得到了这个

NSURL *url = [NSURL URLWithString:@"http://test.myserver.com"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
RKObjectRequestOperation *objectRequestOperation = [[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:@[ responseDescriptor ]];

[objectRequestOperation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
RKLogInfo(@"Load collection of Articles: %@", mappingResult.array);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
RKLogError(@"Operation failed with error: %@", error);
}];

         [objectRequestOperation start];

这似乎联系了服务器,但不可避免地记录了以下错误

restkit.network:RKObjectRequestOperation.m:296 对象请求失败:底层 HTTP 请求操作失败并出现错误:Error Domain=org.restkit.RestKit.ErrorDomain Code=-1011 “预期状态代码在 (200-299),得到401" 用户信息=0x7884030 {NSLocalizedRecoverySuggestion={ “错误”: { “代码”:401, “消息”:“未经授权:需要身份验证” } }, AFNetworkingOperationFailingURLRequestErrorKey=http://elancovision.umfundi.com>, NSErrorFailingURLKey=http://elancovision.umfundi.com, NSLocalizedDescription=预期状态码在 (200-299), 得到 401, AFNetworkingOperationFailingURLResponseErrorKey=}

问题当然是我如何将用户名和密码添加到请求中。

抱歉这个菜鸟问题!

【问题讨论】:

  • 您需要知道使用哪种协议对 API 进行身份验证。你能在你的问题中准确地说出来吗? RESTKit 的网络层依赖于 AFNetworking。因此,就身份验证而言,您将不得不处理这个库。
  • 我能告诉你的最好的就是服务器端是使用restler库用PHP编写的。
  • 使用'BasicAuthenticaton'

标签: restkit restkit-0.20


【解决方案1】:

对于基本的 HTTP 身份验证,用户名和密码应插入到每个请求的 HTTP 请求授权标头字段中。

首先,我建议您使用 RKObjectManager 来集中配置请求和映射。 http://restkit.org/api/latest/Classes/RKObjectManager.html RKObjectManager 可以存储网络参数(通过 AFNetworking 库),然后根据用户名/密码、路径、对象映射构建适当的 http 查询。

调整你的例子,它会给出类似的东西:

NSURL* url = [[NSURL alloc]initWithString:@"http://test.myserver.com"];
RKObjectManager* objectManager = [RKObjectManager managerWithBaseURL:url];
[objectManager.HTTPClient setAuthorizationHeaderWithUsername:@"username" password:@"password"];

//NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLRequest *request = [objectManager requestWithObject:nil method:RKRequestMethodGET path:@"/yourAPI/yourmethod" parameters:nil];

RKObjectRequestOperation *objectRequestOperation = [[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:@[ responseDescriptor ]];

[objectRequestOperation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
        RKLogInfo(@"Load collection of Articles: %@", mappingResult.array);
    } failure:^(RKObjectRequestOperation *operation, NSError *error) {
        RKLogError(@"Operation failed with error: %@", error);
    }];

[objectRequestOperation start];

如果身份验证有效,查看 RESTKit wiki 应该会为您提供构建正确映射的下一个提示:https://github.com/RestKit/RestKit/wiki/Object-mapping

【讨论】:

  • 谢谢。正如您发布的那样,我通过蛮力得出了几乎完全相同的答案!正如您所说,wiki 提供了提示,它仍然直接关注 0.10 版,并且 0.2 版的更改非常重要。对......接下来我的挑战,如何使用我现在可以从服务器获取的信息! :)
  • +1 for [objectManager.HTTPClient setAuthorizationHeaderWithUsername:@"username" password:@"password"]; -- 我刚刚尝试使用 setDefaultHeader 单独设置用户名/密码,但没有成功。你的建议成功了。
【解决方案2】:

我的解决方案:

// Build a RestKit manager object to look after the restful stuff
RKObjectManager *manager =  [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://test.myserver.com"]];;

// Hash the GUI input password string and pass the username in plain text
NSString *md5PW = [umfundiCommon md5:passwordField.text];           
[manager.HTTPClient setAuthorizationHeaderWithUsername:userField.text password:md5PW];

RKObjectMapping *WebResponse = [RKObjectMapping mappingForClass:[WSObject class]];

        [WebResponse addAttributeMappingsFromDictionary:@{@"id_user":@"id_user", @"datalocation": @"datalocation", @"country":@"country", @"data": @"data", @"login": @"login", @"password": @"password", @"accessLevel": @"accessLevel", @"timestamp": @"timestamp", @"datahash": @"datahash"}];

RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:WebResponse pathPattern:nil keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
// Add the above response descriptor to the manager
[manager addResponseDescriptor:responseDescriptor];

// the getObject makes the call using the stuff assembled into the manager Object and drops into either the success or the failure routines.
[manager getObject:nil path:@"" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *result)
{
NSLog (@"Server WS call success:");

NSArray *theresults = [result array];              
for (WSObject *item in theresults) {
    NSLog(@"datahash=%@",item.datahash);
    NSLog(@"user_id=%@",item.id_user);
    }
}  failure:^(RKObjectRequestOperation * operation, NSError * error)
    {
    NSLog (@"Server WS call failure: operation: %@ \n\nerror: %@", operation, error);
    }];

........

【讨论】: