聊聊SSL證書

寫這篇文章的目的

之前在做一個(gè)奇葩的定制,遇到提示“無(wú)法驗(yàn)證服務(wù)器的身份,可能鏈接到偽裝服務(wù)器”的錯(cuò)誤,然而我自己這邊的demo沒(méi)有出現(xiàn)這個(gè)問(wèn)題,一度表示很無(wú)奈。還有一個(gè)是使用SDWebImage加載網(wǎng)絡(luò)圖片時(shí),圖片下載失敗(圖片地址也是https),還有一個(gè)是使用UIImageView+AFNetworking加載圖片時(shí),請(qǐng)求被cancel。跟客戶溝通了很久,才解決了以上問(wèn)題,所以想寫篇文章記錄一下。

什么是SSL

SSL證書是數(shù)字證書的一種,也稱為SSL服務(wù)器證書,SSL證書通過(guò)在客戶端瀏覽器和Web服務(wù)器建立一條SSL安全通道,實(shí)現(xiàn)數(shù)據(jù)信息在客戶端和服務(wù)器之間的加密傳輸,可以防止數(shù)據(jù)信息的泄露,保證了雙方傳遞信息的安全性,而且用戶可以通過(guò)服務(wù)器證書驗(yàn)證他所訪問(wèn)的網(wǎng)站是否是真實(shí)可靠。

蘋果ATS對(duì)SSL做了以下要求:
  • 使用SHA2級(jí)別的證書簽名算法,例如SHA-256, SHA-512等;
  • 證書公鑰算法使用RSA 2048位及以上,或使用更高的算法ECC 256加密算法;

從權(quán)威機(jī)構(gòu)認(rèn)證過(guò)的證書一般都符合蘋果ATS要求,自建證書基本都需要APP去繞過(guò)證書校驗(yàn)的步驟。符合要求的很好處理,接下來(lái)說(shuō)說(shuō)如何繞過(guò)證書校驗(yàn)。

iOS繞過(guò)https證書校驗(yàn)

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];
}

但是下面代理方法已經(jīng)廢棄

- (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));

在這次定制中,就是因?yàn)闆](méi)有進(jìn)入下面兩代理方法,導(dǎo)致客戶那邊無(wú)法打開(kāi)app內(nèi)嵌到網(wǎng)頁(yè),所以要用下面的方法代替

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

SDWebView

這個(gè)問(wèn)題沒(méi)有解決,但是代碼中已經(jīng)設(shè)置了繞過(guò)證書校驗(yàn),

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

這個(gè)方法中options配置為SDWebImageAllowInvalidSSLCertificates(信任所有證書),在SDWebImageDownloader中也對(duì)證書校驗(yàn)進(jìn)行了處理,

- (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中進(jìn)行,跟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是因?yàn)锳FImageDownloader中AFHTTPSessionManager沒(méi)有設(shè)置securityPolicy,只要在initWithSessionConfiguration:方法中添加sessionManager.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];就可以繞過(guò)證書校驗(yàn)。

- (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]];
}

以上就是這次踩完坑后的收獲,有什么不對(duì)的地方還請(qǐng)路過(guò)的朋友們指點(diǎn)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 小小的你如同滄海一粟 揮舞著不甘的小手 踢踏著不屈的小腳 你可知 你小小的眼眸里 凝聚了星辰大海 你小小的身軀里 ...
    櫻圃閱讀 306評(píng)論 1 3
  • 今天是大年初一,昨天整整擺了一天攤,家里年年都是這樣的,五點(diǎn)多才從街上擺攤回去。賺錢的辛苦也深深理解了一個(gè)...
    瑞的平凡生活閱讀 291評(píng)論 0 7
  • 曾經(jīng)聽(tīng)到一句話,關(guān)于孤獨(dú):不合群是表面的孤獨(dú),合群了才是內(nèi)心的孤獨(dú)。
    def3973c167a閱讀 137評(píng)論 0 0

友情鏈接更多精彩內(nèi)容