iOS HTTPS 请求 101 [英] iOS HTTPS requests 101
问题描述
NSURLConnection/CFURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9813)
非常非常令人沮丧!我一直在用这个拉我的头发几个小时.我在我的 Linode 服务器上使用自签名证书.端口是 8000,无法让它在 443 上工作.我不相信这就是原因.这是我的代码,它是 99% 的样板:
Very, very frustrating! I've been pulling my hair for hours with this. I'm using a self-signed certificate on my Linode server. The port is 8000, couldn't get it to work on 443. I don't believe this is the reason though. Here's my code, it's 99% boilerplate:
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]]);
}
天哪!帮助!
更新
它与这个委托方法一起工作.我正在收到回复,但出现问题.
It worked with this delegate method. I'm receiving the response, but there is a problem.
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
[[challenge sender] useCredential:[NSURLCredential
credentialWithUser:@"user"
password:@"password"
persistence:NSURLCredentialPersistencePermanent] forAuthenticationChallenge:challenge];
}
我提供的用户"和密码"是完全随机的,不会被服务器检查.如何在我的服务器上接受连接之前验证凭据?
The "user" and "password" that I have provided are completely random and aren't checked by the server. How can I verify the credentials before accepting the connection on my server?
我正在运行 Node.js 服务器
I'm running a Node.js server
推荐答案
获取相应的错误描述可能会有所帮助:
Getting the corresponding error description may help:
所以,首先错误域 kCFStreamErrorDomainSSL
表示错误代码是 Security/SecureTransport.h 中定义的 SSL 错误代码:
So, first the error domain kCFStreamErrorDomainSSL
means that the error code is an SSL error code as defined in Security/SecureTransport.h:
kCFStreamErrorDomainSSL,-9813 表示:
kCFStreamErrorDomainSSL, -9813 means:
errSSLNoRootCert = -9813,/* 证书链未经 root 验证 */
这只是意味着,您没有受信任的根证书,并且由于身份验证失败而导致连接失败.
And that simply means, you have no trusted root certificate and the connection fails because of that authentication failure.
为服务器信任身份验证提供设备上的根证书即可.
Provide a root certificate on the device for the server trust authentication and you are fine.
有几种方法可以使用自签名证书实现服务器信任身份验证,一种比另一种更安全.
There are a few approaches to implement server trust authentication with self-signed certificates, the one more secure than the other.
最简单的方法需要一个自签名证书,该证书存储在应用程序包中,然后检索并简单地进行字节比较.下面是一个例子:
The simplest approach requires a self-signed certificate which is stored in the bundle of the app, then retrieved and simply byte-compared. Here is an example:
这些也是必读的:技术说明 TN2232HTTPS 服务器信任评估和技术问答 QA1360 描述kSecTrustResultUnspecified 错误.
更优选的方法是使用您可以成为自己的 CA(证书颁发机构).也就是说,您创建自己的 CA 并使用该 CA 签署您的证书.
The more preferred approach is to use a CA (Certificate Authority) which you can be yourself. That is, you create your own CA and your certificates signed with this CA.
步骤类似:
- 在您的应用中捆绑 CA 根证书的 DER 文件.
如下处理服务器信任认证:
- Bundel the DER file of your CA's root certificate in your app.
Handle the server trust authentication as follows:
- 获取身份验证质询
- 从挑战中检索信任对象
- 根据包中的数据创建证书对象
- 使用函数
SecTrustSetAnchorCertificates
将证书对象设置为信任对象的锚点. - 评估信任
- get the authentication challenge
- retrieve the trust object from the challenge
- create a certificate object from the data in your bundle
- set the certificate object as an anchor to the trust object using function
SecTrustSetAnchorCertificates
. - evaluate the trust
这篇关于iOS HTTPS 请求 101的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!