AFNetworking访问https出现"NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9813"

来源:互联网 发布:ch341a编程器教程 编辑:程序博客网 时间:2024/06/01 07:42

       使用AFNetworking来访问http请求非常方便快捷,最简单的请求代码如下:

#import "HSTestHTTPSViewController.h"#import <AFNetworking/AFNetworking.h>@interface HSTestHTTPSViewController ()@end@implementation HSTestHTTPSViewController- (void)viewDidLoad {    [super viewDidLoad];    NSString *URLString = @"http://localhost:8000";    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];    manager.requestSerializer = [AFHTTPRequestSerializer serializer];    manager.responseSerializer = [AFHTTPResponseSerializer serializer];    [manager GET:URLString parameters:nil progress:nil          success:^(NSURLSessionDataTask *task, id responseObject) {              //返回NSData,转化为String输出              NSString *JSONString = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];              NSLog(@"%@", JSONString);          }          failure:^(NSURLSessionDataTask *task, NSError *error) {              NSLog(@"%@", error);          }];}@end

      当然,使用上述代码来请求http能够成功,但是当我们要访问https的时候,如果仅仅是把上述的请求URL修改成对应的https,那么很有可能会出现如下报错:

NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9813)
Error Domain=NSURLErrorDomain Code=-1202 "The certificate for this server is invalid. 
You might be connecting to a server that is pretending to be “localhost” which could put your confidential information at risk." UserInfo={NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 0x600000108820>, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9813, NSErrorPeerCertificateChainKey=
(
    "<cert(0x7f9bcd84ea00) s: chenyufeng i: chenyufeng>"
), NSUnderlyingError=0x600000057730 {Error Domain=kCFErrorDomainCFNetwork Code=-1202 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, kCFStreamPropertySSLPeerTrust=<SecTrustRef: 0x600000108820>, _kCFNetworkCFStreamSSLErrorOriginalValue=-9813, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9813, kCFStreamPropertySSLPeerCertificates=
(
    "<cert(0x7f9bcd84ea00) s: chenyufeng i: chenyufeng>"
)}}, NSLocalizedDescription=The certificate for this server is invalid. You might be connecting to a server that is pretending to be “localhost” which could put your confidential information at risk., NSErrorFailingURLKey=https://localhost:8001/, NSErrorFailingURLStringKey=https://localhost:8001/, NSErrorClientCertificateStateKey=0}


     出现以上问题的主要原因是https证书是自签名证书,没有经过第三方机构认证(关于生成自签名证书和nodejs配置自签名证书可以了解《nodejs开发——express配置自签名https服务器》这篇博客)。一个经过认证的证书一般不会出现以上问题。那么在服务端https证书不变的情况下,如何在iOS客户端修复该问题呢?

(1)从服务端那里拿到证书crt后缀文件,我这里的文件名为“file.crt”. (建议看下nodejs开发——express配置自签名https服务器)。然后使用该crt文件生成用于iOS的.cer文件,我这里的文件名为“client.cer”.  生成命令如下:

openssl x509 -in file.crt -out client.cer -outform der


生成前crt与生成后的cer文件如下:




(2)然后把client.cer文件复制到iOS项目目录下,然后在Build Phases中的Copy Bundle Resources中选中该cer文件进行添加:






(3)然后把AFN的网络请求代码修改如下:主要增加Security设置

#import "HSTestHTTPSViewController.h"#import <AFNetworking/AFNetworking.h>@interface HSTestHTTPSViewController ()@end@implementation HSTestHTTPSViewController- (void)viewDidLoad {    [super viewDidLoad];    NSString *URLString = @"https://localhost:8001";    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];    manager.requestSerializer = [AFHTTPRequestSerializer serializer];    manager.responseSerializer = [AFHTTPResponseSerializer serializer];    //增加AFSecurityPolicy设置    AFSecurityPolicy * securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];    securityPolicy.allowInvalidCertificates = YES;    securityPolicy.validatesDomainName = NO;    manager.securityPolicy = securityPolicy;    [manager GET:URLString parameters:nil progress:nil          success:^(NSURLSessionDataTask *task, id responseObject) {              //返回NSData,转化为String输出              NSString *JSONString = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];              NSLog(@"%@", JSONString);          }          failure:^(NSURLSessionDataTask *task, NSError *error) {              NSLog(@"%@", error);          }];}@end

      经过测试,能成功接收到https的返回结果。


2 1
原创粉丝点击