iOS HTTPS 请求 101

Posted

技术标签:

【中文标题】iOS HTTPS 请求 101【英文标题】:iOS HTTPS requests 101 【发布时间】:2013-08-04 16:56:25 【问题描述】:
NSURLConnection/CFURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9813)

非常非常令人沮丧!我已经为此拉了几个小时的头发。我在我的 Linode 服务器上使用自签名证书。端口是 8000,无法让它在 443 上工作。我不相信这是原因。这是我的代码,它是 99% 的样板:

NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"https://www.myserver.com:8000/test.json"]];
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];

在底部:

#pragma mark NSURLConnectionDelegate

- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace 
    NSLog(@"protectionSpace: %@", [protectionSpace authenticationMethod]);

    // We only know how to handle NTLM authentication.
    if([[protectionSpace authenticationMethod] isEqualToString:NSURLAuthenticationMethodNTLM])
        return YES;

    // Explicitly reject ServerTrust. This is occasionally sent by IIS.
    if([[protectionSpace authenticationMethod] isEqualToString:NSURLAuthenticationMethodServerTrust])
        return NO;

    return NO;


- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge 
    [[challenge sender] continueWithoutCredentialForAuthenticationChallenge:challenge];


- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response 
    NSLog(@"%@", response);


- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 
    NSLog(@"%@", data);


- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 
    NSLog(@"didFailWithError");
    NSLog([NSString stringWithFormat:@"Connection failed: %@", [error description]]);

天哪,救命!

更新

它与这个委托方法一起工作。我正在收到回复,但有问题。

- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge 
    [[challenge sender] useCredential:[NSURLCredential
                                       credentialWithUser:@"user"
                                       password:@"password"
                                       persistence:NSURLCredentialPersistencePermanent] forAuthenticationChallenge:challenge];


我提供的“用户”和“密码”是完全随机的,服务器不会检查。 如何在我的服务器上接受连接之前验证凭据?

编辑:我正在运行 Node.js 服务器

【问题讨论】:

“我提供的“用户”和“密码”是完全随机的,服务器不会检查”——这是一个不同的问题。您应该将其作为一个单独的问题提出,并可能链接回该问题。 Linode 配置可能是题外话,所以你可能不得不徘徊到超级用户或服务器故障。 (您可能应该接受 Fonix 的回答,因为它似乎帮助您解决了问题)。 【参考方案1】:

获取相应的错误描述可能会有所帮助:

因此,首先错误域kCFStreamErrorDomainSSL 表示错误代码是Security/SecureTransport.h 中定义的SSL 错误代码:

kCFStreamErrorDomainSSL, -9813 表示:

errSSLNoRootCert = -9813, /* cert chain not verified by root */

这只是意味着,您没有受信任的根证书,并且由于身份验证失败而导致连接失败。

在设备上为服务器信任身份验证提供根证书就可以了。

有几种方法可以使用自签名证书实现服务器信任身份验证,其中一种比另一种更安全。

最简单的方法需要存储在应用程序包中的自签名证书,然后检索并简单地进行字节比较。这是一个例子:

Implementing server trust authentication with a self-signed certificate.

这些也是必读的:Technical Note TN2232 HTTPS Server Trust Evaluation 和 Technical Q&A QA1360 Describing the kSecTrustResultUnspecified error。

更优选的方法是使用您可以自己的 CA(证书颁发机构)。也就是说,您创建自己的 CA 并使用此 CA 签署证书。

步骤类似:

    在您的应用中捆绑 CA 根证书的 DER 文件。

    如下处理服务器信任认证:

      获取身份验证质询 从质询中检索信任对象 根据捆绑包中的数据创建证书对象 使用函数SecTrustSetAnchorCertificates将证书对象设置为信任对象的锚。 评估信任度

【讨论】:

这里是解密其他错误码的网址...opensource.apple.com/source/libsecurity_ssl/…【参考方案2】:

不确定这是否真的能解决问题,但它可能会有所帮助。你应该使用

– connection:willSendRequestForAuthenticationChallenge:

因为其他方法已被弃用。看看NSURLConnectionDelegate protocol的概述

【讨论】:

不幸的是,我对这个认证东西有点菜鸟,所以我不确定

以上是关于iOS HTTPS 请求 101的主要内容,如果未能解决你的问题,请参考以下文章

iOS使用自签名证书实现HTTPS请求

iOS内置证书,校验https请求

iOS https请求 NSURLSessionDataTask

使用HTTPS请求http.nonproxyhosts Play框架1.2.5问题,怎么解决

fiddler抓取https请求(android/ios)

iOS AFNetworking框架HTTPS请求配置