2013-08-03 113 views
14
NSURLConnection/CFURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9813) 

非常非常令人沮丧!我已经用这个拉了几个小时的头发。我在我的Linode服务器上使用自签名证书。端口是8000,无法在443上运行。我不认为这是原因。这里是我的代码,这是99%的样板:iOS HTTPS请求101

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]]); 
} 

OMG帮助!

UPDATE

它的工作与此委托方法。我收到了回复,但有一个问题。

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

} 

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

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

+0

’的‘用户’和”密码 - 这是一个不同的问题。你应该把它作为一个单独的问题来问,也许可以回到这个问题上。 Linode配置可能是无关紧要的,所以您可能不得不徘徊到超级用户或服务器故障。 (你应该接受Fonix的回答,因为它似乎帮助你解决了这个问题)。 – jww

回答

2

不知道这是否会真正解决问题,但它可能会有所帮助。您应该使用

– connection:willSendRequestForAuthenticationChallenge: 

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

+0

几乎工作,看到我更新的问题 –

+0

不幸的是我有点noob这个身份验证的东西,所以我不知道 – Fonix

8

获取相应的错误描述概览可以帮助:

因此,第一误差域kCFStreamErrorDomainSSL意味着错误代码是在安全/ SecureTransport.h定义的SSL错误代码:

kCFStreamErrorDomainSSL,-9813表示:

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

这只是意味着,你有没有受信任的根证书和连接到由于该认证失败,ction失败。

在设备上为服务器信任认证提供根证书,你很好。

有几种方法可以使用自签名证书实现服务器信任认证,这是一种比另一种更安全的方法。

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

Implementing server trust authentication with a self-signed certificate

这些是必读:Technical Note TN2232 HTTPS Server Trust EvaluationTechnical Q&A QA1360 Describing the kSecTrustResultUnspecified error

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

的步骤类似:

  1. Bundel您的CA根证书在您的应用程序的DER文件。
  2. 处理服务器信任认证如下:

    1. 获得认证挑战
    2. 从挑战
    3. 获取信任的对象在你的包的数据创建一个证书对象
    4. 设置证书对象作为使用函数SecTrustSetAnchorCertificates的信任对象的锚点。
    5. 评估“我提供的是完全随机的,而不是由服务器检查‘信任
+4

这里是解密其他错误代码的URL ... http://www.opensource.apple.com/源极/ libsecurity_ssl/libsecurity_ssl-36800/LIB/SecureTransport.h – cat