美文网首页
聊聊SSL证书

聊聊SSL证书

作者: CCCRick | 来源:发表于2018-07-24 19:54 被阅读0次

    写这篇文章的目的

    之前在做一个奇葩的定制,遇到提示“无法验证服务器的身份,可能链接到伪装服务器”的错误,然而我自己这边的demo没有出现这个问题,一度表示很无奈。还有一个是使用SDWebImage加载网络图片时,图片下载失败(图片地址也是https),还有一个是使用UIImageView+AFNetworking加载图片时,请求被cancel。跟客户沟通了很久,才解决了以上问题,所以想写篇文章记录一下。

    什么是SSL

    SSL证书是数字证书的一种,也称为SSL服务器证书,SSL证书通过在客户端浏览器和Web服务器建立一条SSL安全通道,实现数据信息在客户端和服务器之间的加密传输,可以防止数据信息的泄露,保证了双方传递信息的安全性,而且用户可以通过服务器证书验证他所访问的网站是否是真实可靠。

    苹果ATS对SSL做了以下要求:
    • 使用SHA2级别的证书签名算法,例如SHA-256, SHA-512等;
    • 证书公钥算法使用RSA 2048位及以上,或使用更高的算法ECC 256加密算法;

    从权威机构认证过的证书一般都符合苹果ATS要求,自建证书基本都需要APP去绕过证书校验的步骤。符合要求的很好处理,接下来说说如何绕过证书校验。

    iOS绕过https证书校验

    UIWebView

    - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
        
        if (!_authenticated) {
            _authenticated = YES;
            _urlConnection = [[NSURLConnection alloc] initWithRequest:_requestW delegate:self];
            [_urlConnection start];
            return NO;
        }
        return YES;
    }
    
    - (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
        
        if ([challenge previousFailureCount] == 0){
            _authenticated = YES;
            NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
            [challenge.sender useCredential:credential forAuthenticationChallenge:challenge];
        } else{
            [[challenge sender] cancelAuthenticationChallenge:challenge];
        }
    }
    
    - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
        
        _authenticated = YES;
        [self loadRequest:_requestW];
        [_urlConnection cancel];
    }
    
    - (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
        
        return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
    }
    

    但是下面代理方法已经废弃

    - (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge API_DEPRECATED("Use -connection:willSendRequestForAuthenticationChallenge: instead.", macos(10.2,10.10), ios(2.0,8.0), watchos(2.0,2.0), tvos(9.0,9.0));
    

    在这次定制中,就是因为没有进入下面两代理方法,导致客户那边无法打开app内嵌到网页,所以要用下面的方法代替

    - (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;
    

    SDWebView

    这个问题没有解决,但是代码中已经设置了绕过证书校验,

    - (void)sd_setImageWithURL:(nullable NSURL *)url
              placeholderImage:(nullable UIImage *)placeholder
                       options:(SDWebImageOptions)options
    

    这个方法中options配置为SDWebImageAllowInvalidSSLCertificates(信任所有证书),在SDWebImageDownloader中也对证书校验进行了处理,

    - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler {
    
       // Identify the operation that runs this task and pass it the delegate method
       NSOperation<SDWebImageDownloaderOperationInterface> *dataOperation = [self operationWithTask:task];
       if ([dataOperation respondsToSelector:@selector(URLSession:task:didReceiveChallenge:completionHandler:)]) {
           [dataOperation URLSession:session task:task didReceiveChallenge:challenge completionHandler:completionHandler];
       } else {
           if (completionHandler) {
               completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
           }
       }
    }
    

    真正的处理是在SDWebImageDownloaderOperation中进行,跟webView的处理方式是一样的。

    - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler {
        
        NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
        __block NSURLCredential *credential = nil;
        
        if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
            if (!(self.options & SDWebImageDownloaderAllowInvalidSSLCertificates)) {
                disposition = NSURLSessionAuthChallengePerformDefaultHandling;
            } else {
                credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
                disposition = NSURLSessionAuthChallengeUseCredential;
            }
        } else {
            if (challenge.previousFailureCount == 0) {
                if (self.credential) {
                    credential = self.credential;
                    disposition = NSURLSessionAuthChallengeUseCredential;
                } else {
                    disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
                }
            } else {
                disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
            }
        }
        
        if (completionHandler) {
            completionHandler(disposition, credential);
        }
    }
    

    AFNetworking

    AF是因为AFImageDownloader中AFHTTPSessionManager没有设置securityPolicy,只要在initWithSessionConfiguration:方法中添加sessionManager.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];就可以绕过证书校验。

    - (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration {
        AFHTTPSessionManager *sessionManager = [[AFHTTPSessionManager alloc] initWithSessionConfiguration:configuration];
        sessionManager.responseSerializer = [AFImageResponseSerializer serializer];
        sessionManager.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
    
        return [self initWithSessionManager:sessionManager
                     downloadPrioritization:AFImageDownloadPrioritizationFIFO
                     maximumActiveDownloads:4
                                 imageCache:[[AFAutoPurgingImageCache alloc] init]];
    }
    

    以上就是这次踩完坑后的收获,有什么不对的地方还请路过的朋友们指点。

    相关文章

      网友评论

          本文标题:聊聊SSL证书

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