iOS HTTPS请求101

14
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配置可能不属于主题,因此您可能需要转到Super User或Server Fault。 (而且,您应该接受Fonix的答案,因为它似乎已经帮助您解决了问题)。 - jww
2个回答

8
获取相应的错误描述可能会有所帮助:
首先,错误域kCFStreamErrorDomainSSL表示错误代码是在Security/SecureTransport.h中定义的SSL错误代码:
kCFStreamErrorDomainSSL,-9813表示: errSSLNoRootCert = -9813,/*未通过根证书验证*/ 这意味着您没有受信任的根证书,并且由于身份验证失败而连接失败。
为设备提供一个根证书以进行服务器信任身份验证即可解决问题。
有几种方法可以使用自签名证书实现服务器信任身份验证,其中一种比另一种更安全。
最简单的方法需要一个自签名证书,该证书存储在应用程序的包中,然后检索并进行字节比较。以下是一个示例: 使用自签名证书实现服务器信任身份验证
These are a must read also: 技术笔记TN2232 HTTPS服务器信任评估技术问答QA1360描述kSecTrustResultUnspecified错误
更为推荐的方法是使用可以成为自己的CA(证书颁发机构)。也就是说,您创建自己的CA和用该CA签名的证书。
步骤类似:
  1. 将您的CA根证书的DER文件打包到应用程序中。
  2. 按以下方式处理服务器信任验证:

    1. 获取身份验证挑战
    2. 从挑战中检索信任对象
    3. 从您的捆绑包数据中创建证书对象
    4. 使用函数SecTrustSetAnchorCertificates将证书对象设置为信任对象的锚点。
    5. 评估信任

4
这是解密其他错误代码的URL... http://www.opensource.apple.com/source/libsecurity_ssl/libsecurity_ssl-36800/lib/SecureTransport.h - cat

2

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

 connection:willSendRequestForAuthenticationChallenge:

由于其他方法已被弃用,请查看NSURLConnectionDelegate协议概述


很不幸,我在认证方面有点新手,所以我不确定。 - Fonix

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接