1. 程式人生 > >Cordova下自簽名證書無法訪問https問題(IOS和Android)

Cordova下自簽名證書無法訪問https問題(IOS和Android)

最近準備將專案上架到AppStore,但從17年開始,AppStore稽核條件要求所有網路請求都為https,所以就在內網(192.……)布好了自測環境,並將環境對映到了公網(58.……)。接著問題就來了:

1,使用chrome(51.0.2704.103版本)除錯時,內網和外網都可以正常訪問;

2,使用Safari除錯時,內網正常訪問,外網無法訪問;

3,安裝到iPhone7上,內網正常訪問,外網無法訪問;

4,安裝到三星C7(Android 6.0.1)上,內網正常訪問,外網無法訪問;

5,安裝到Cube平板(Android 4.4.4)上,內網和外網都可以正常訪問;

總結分析了一下,覺得可能是以下原因造成的:

1,埠對映問題;

2,後臺bug;

3,瀏覽器核心原因;

4,證書問題;

接著就一個個的排除。首先重新檢查了一下nginx配置,沒什麼問題,而且既然內外網瀏覽器都可以正常訪問,就說明埠對映是ok的;給後臺打了個補丁切換到http,測試一切ok,再切換回https問題如期重現,因為我們是單向認證,而且電腦上chrome瀏覽器是可以正常訪問的,所以後臺bug也可以排除掉了;至於android手機瀏覽器核心,眾所周知,Android4.4之前的瀏覽器核心是WebKit,4.4切換到了Chromium(核心是Webkit的分支Blink),也就是說三星C7和Cube系統瀏覽器核心是一樣的,只是核心版本不同。為了進一步確認,我在三星C7上裝了個火狐瀏覽器,在火狐瀏覽器中輸入外網IP埠提交,提示證書無效或不可信任,點選繼續前往順利進入;接著返回我們的app,果然app在外網也可以正常使用了!至此Android上問題確認:是不同Chromium版本對自簽名證書信任上出了問題!再來定位IOS問題,通過nginx日誌,發現iphone7上訪問外網時nginx根本沒有接收到訪問請求,再通過Xcode除錯日誌,發現外網訪問時報錯:NSURLSession/NSURLConnection HTTP load failed kCFStreamErrorDomainSSL, -9813,還是對自簽名證書的信任問題!

定位到了問題就好辦了:使用第三方正規證書或移動端信任所有證書。由於第三方證書都是頒發給域名而不是ip,而我們的應用場景是通過ip訪問,所以即使有了第三方的正規證書也是沒用的。只有在移動端解決了(讓應用信任所有證書)。解決辦法如下:

IOS上:

在appDelegate.m檔案中新增以下程式碼:

@implementation NSURLRequest(DataController) 
+ (BOOL)allowsAnyHTTPSCertificateForHost:(NSString *)host 
{ 
return YES; 
} 
@end

Android上:

修改 org.apache.cordova.engine.SystemWebViewClient.java檔案

onReceivedSslError()方法為如下:

/**
     * Notify the host application that an SSL error occurred while loading a resource.
     * The host application must call either handler.cancel() or handler.proceed().
     * Note that the decision may be retained for use in response to future SSL errors.
     * The default behavior is to cancel the load.
     *
     * @param view          The WebView that is initiating the callback.
     * @param handler       An SslErrorHandler object that will handle the user's response.
     * @param error         The SSL error object.
     */
    @TargetApi(8)
    @Override
    public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
        handler.proceed();
    }

以上,問題順利解決!又經過一翻折騰終於成功提交到AppStore,坐等稽核通過。