美文网首页
iOS 内置证书 校验https请求

iOS 内置证书 校验https请求

作者: 红色海_ | 来源:发表于2019-12-04 16:39 被阅读0次

https://www.cnblogs.com/lizilong/p/7527305.html

处于安全的考虑需要https请求,但是为了防止域名解析很多情况下会使用IP进行访问。
一般的服务不会针对IP去申请证书,所以我们可以自己实现ssl登录过程,保证请求的安全性。

一.首先需要自己本地生成ssl证书以及搭建一个本地服务

Mac apache本地配置ssl证书 及 iOS OTA部署: http://www.jianshu.com/p/bd016015efe7

生成的crt转换成cer的方法

openssl x509 -in test.crt -out test.cer -outform der

二.实现代码

初始化NSURLSession,将证书导入对应的xcode项目中

NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration ephemeralSessionConfiguration];
configuration.requestCachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
configuration.timeoutIntervalForRequest = 120;
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration
                                                 delegate:self
                                            delegateQueue:[[NSOperationQueue alloc] init]];

生成的ssl证书需要设置ip,而且校验的时候也会去校验这个ip。但是更多情况下是不去校验这个ip的,因为代码内部可能只有一个证书,但是服务可能会有多套部署,如果去校验ip,会限制服务的扩展(很多项目都会做自己的DNS策略,ip经常会改变)。

- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
 completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler
{
    NSString *host = challenge.protectionSpace.host;
    BOOL isIp = [self _isIp:host];
    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
        if (isIp) {
            // Get
            NSData *certData =[NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"server" ofType:@"cer"]];
            if (certData) {
                SecTrustRef trust = [[challenge protectionSpace] serverTrust];
                
                NSMutableArray *policies = [NSMutableArray array];
          //如果需要校验IP,需要把下面的注释打开,把下面X509这段代码注释掉
          //[policies addObject:(__bridge_transfer id)SecPolicyCreateSSL(true, (__bridge CFStringRef)domain)];
                [policies addObject:(__bridge_transfer id)SecPolicyCreateBasicX509()];
                SecTrustSetPolicies(trust, (__bridge CFArrayRef)policies);
                
                SecCertificateRef rootcert = SecCertificateCreateWithData(kCFAllocatorDefault,CFBridgingRetain(certData));
                const void *array[1] = { rootcert };
                CFArrayRef certs = CFArrayCreate(NULL, array, 1, &kCFTypeArrayCallBacks);
                int err;
                SecTrustResultType trustResult = 0;
                err = SecTrustSetAnchorCertificates(trust, certs);
                if (err == noErr) {
                    err = SecTrustEvaluate(trust,&trustResult);
                }
                BOOL trusted = (err == noErr) && ((trustResult == kSecTrustResultProceed) || (trustResult == kSecTrustResultUnspecified));
                if (!trusted) {
                    NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] ;
                    completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
                } else {
                    //如果校验失败了,就校验一下证书数据,一般不建议走这段逻辑,因为不能够保证服务是否安全
                    NSMutableArray *pinnedCertificates = [NSMutableArray array];
                    [pinnedCertificates addObject:(__bridge_transfer id)SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certData)];
                    SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)pinnedCertificates);
                    
                    NSArray *serverCertificates = [self _certificateTrustChainForServerTrust:trust];
                    
                    for (NSData *trustChainCertificate in [serverCertificates reverseObjectEnumerator]) {
                        if ([certData isEqualToData:trustChainCertificate]) {
                            NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] ;
                            completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
                        }
                    }
                }
            }
        } else {
            NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
            completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
        }
    }
}

- (BOOL)_isIp:(NSString*)aHost
{
    NSString *regex = @"((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)";
    NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
    
    return [pred evaluateWithObject:aHost];
}

- (NSArray *)_certificateTrustChainForServerTrust:(SecTrustRef)serverTrust
{
    CFIndex certificateCount = SecTrustGetCertificateCount(serverTrust);
    NSMutableArray *trustChain = [NSMutableArray arrayWithCapacity:(NSUInteger)certificateCount];
    
    for (CFIndex i = 0; i < certificateCount; i++) {
        SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, i);
        [trustChain addObject:(__bridge_transfer NSData *)SecCertificateCopyData(certificate)];
    }
    
    return [NSArray arrayWithArray:trustChain];
}

https请求构建

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://127.0.0.1:443/index.html"]];
    
    NSURLSessionDataTask *task = [_session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        completionHandler(((NSHTTPURLResponse*)response).statusCode, data ? [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] : nil, error);
    }];
    
    [task resume];

相关文章

  • iOS 内置证书 校验https请求

    https://www.cnblogs.com/lizilong/p/7527305.html 处于安全的考虑需要...

  • HTTPS

    iOS客户端校验https网络请求证书 iOS开发 支持https请求以及https请求的抓包 NSURLConn...

  • AFN支持https后能否抓包的对应设置

    1、支持https,校验证书的合法性,不可以使用抓包工具拦截请求。 2、支持https,不校验证书的合法性,可以使...

  • Https证书校验

    客户端校验服务器的证书,一般有两种情况: 直接校验服务器下发的证书,并与本地的证书作对比 证书锁定法,直接利用本地...

  • HTTPS证书校验

    HTTPS (全称:Hyper Text Transfer Protocol over SecureSocket ...

  • OkHttp https证书校验

    https证书校验

  • android防抓包(证书强校验)

    背景 常规https抓包方案便是通过内置代理证书来进行抓包的。 其中在7.0以下,如果应用不做证书强校验,直接通过...

  • 当Fresco/Picasso遇到https(2)----访问自

    上文讲述的加载https的时候,不使用证书安全校验。本文讲述-------使用OkHttp请求自签名的https网...

  • Alamofire HTTPS自签名证书校验

    根据项目需求,需要进行HTTPS网络请求并添加证书校验过程,由于没有做过,前前后后研究了两个多星期,才通过校验,可...

  • 屏蔽HTTPS证书校验

    屏蔽HTTPS证书校验 ————————————————————————————————————————— 背景需...

网友评论

      本文标题:iOS 内置证书 校验https请求

      本文链接:https://www.haomeiwen.com/subject/biylgctx.html