iOS 9与REST Web服务的连接失败

时间:2016-03-16 17:01:27

标签: ios objective-c rest nsurlconnection

我对开发iOS应用程序有点新意,我在此应用程序中需要做的一件事就是连接到REST Web服务。我已经在邮差扩展中测试了WS,一切正常,但我似乎无法通过iOS应用程序做同样的事情。这是我用来尝试建立连接的代码:

NSString *wsAuth = [NSString stringWithFormat:@"Basic \%@", [[@"USER:PASS" dataUsingEncoding:NSUTF8StringEncoding] base64EncodedStringWithOptions:nil]];
NSMutableDictionary *post = [[NSMutableDictionary alloc]init];
[post setValue:login forKey:@"user"];
[post setValue:pass forKey:@"pass"];
NSArray *arr = [NSArray arrayWithObjects:post, nil];
NSData *jsonPost = [NSJSONSerialization dataWithJSONObject:arr options:0 error:nil];

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"https://mywebservice.mywebsite.com/auth/"]];
[request setHTTPMethod:@"POST"];
[request setHTTPBody:jsonPost];
[request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setValue:[NSString stringWithFormat:@"%d", [jsonPost length]] forHTTPHeaderField:@"Content-Length"];
[request setValue:wsAuth forHTTPHeaderField:@"Authorization"];

NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[conn start];

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

if([response statusCode] >=200 && [response statusCode] <300) {
    // Process data...
}
else {
    // Present error...
}

我从Xcode收到以下错误:

2016-03-16 11:02:34.658 [31742:2969162] Response = (null)

2016-03-16 11:02:34.659 [31742:2969162] Error =
Error Domain=NSURLErrorDomain Code=-1001 "The request timed out."
UserInfo={NSErrorFailingURLStringKey=https://mywebservice.mywebsite.com/auth/,
_kCFStreamErrorCodeKey=-2102,
NSErrorFailingURLKey=https://mywebservice.mywebsite.com/auth/,
NSLocalizedDescription=The request timed out.,
_kCFStreamErrorDomainKey=4,
NSUnderlyingError=0x7aa5b510 {Error Domain=kCFErrorDomainCFNetwork Code=-1001 "The request timed out."
UserInfo={_kCFStreamErrorCodeKey=-2102,
NSErrorFailingURLStringKey=https://mywebservice.mywebsite.com/auth/, 
NSErrorFailingURLKey=https://mywebservice.mywebsite.com/auth/,
NSLocalizedDescription=The request timed out.,
_kCFStreamErrorDomainKey=4}}}

2016-03-16 11:02:34.693 [31742:2969383] CFNetwork SSLHandshake failed (-9806)
2016-03-16 11:02:34.799 [31742:2969383] CFNetwork SSLHandshake failed (-9802)
2016-03-16 11:02:34.889 [31742:2969383] CFNetwork SSLHandshake failed (-9802)
2016-03-16 11:02:34.890 [31742:2969383] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802)

要了解一些额外的事情。我将其编程为需要与iOS 8或更高版本一起使用的iOS 9应用程序,我在Xcode 7中执行此操作。任何帮助都将不胜感激。

2 个答案:

答案 0 :(得分:0)

您必须在NSAllowsArbitraryLoads文件的YES字典中添加NSAppTransportSecurity密钥至info.plist

enter image description here

答案 1 :(得分:0)

好的,所以我自己想出来了。我想同步请求不起作用,所以我切换到异步。这给了我一个更准确的错误,它告诉我不是传递JSON对象,而是传递一个数组,第一个唯一的条目是JSON对象,导致身份验证失败。

为了澄清,此解决方案包含几个与RESTful Web服务进行通信的对象。这是通过POST完成的,使用JSON对象作为POST变量。此Web服务需要基本身份验证,这是通过第1行和第15行的此代码实现的。最后,这都是基于安全连接和最新SSL证书背后的Web服务。我不是100%确定HTTP请求或自签名证书的工作原理......

附注:我从NSAllowsArbitraryLoads文件中删除了NSAppTransportSecurity密钥和info.plist字典,此解决方案仍然有效。

以下代码为我提供了与安全Web服务的成功连接:

NSString *wsAuth = [NSString stringWithFormat:@"Basic \%@", [[@"USER:PASS" dataUsingEncoding:NSUTF8StringEncoding] base64EncodedStringWithOptions:0]];
NSMutableDictionary *post = [[NSMutableDictionary alloc]init];
[post setValue:login forKey:@"user"];
[post setValue:pass forKey:@"pass"];
NSArray *arr = [NSArray arrayWithObjects:post, nil];
// Note the first value of the array is being referenced, not the entire array.
NSData *jsonPost = [NSJSONSerialization dataWithJSONObject:arr[0] options:0 error:nil];

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"https://mywebservice.mywebsite.com/auth/"]];
[request setHTTPMethod:@"POST"];
[request setHTTPBody:jsonPost];
[request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setValue:[NSString stringWithFormat:@"%d", [jsonPost length]] forHTTPHeaderField:@"Content-Length"];
[request setValue:wsAuth forHTTPHeaderField:@"Authorization"];

[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
    if ([data length] >0 && error == nil) {
        // Process data here...
    }
    else if ([data length] == 0 && error == nil) {
        NSLog(@"Empty Response. Check your credentials.");
    }
    else if (error != nil) {
        NSLog(@"Error = %@", error);
    }
}];