2013-12-23 144 views
5

我有一個需要相互驗證才能加載頁面的網頁。 我得到onReceivedError()與ERROR_FAILED_SSL_HANDSHAKE。在Webkit中打印日誌「無法建立安全連接」。 我已經廣泛搜索,但無法找到答案。有幾個帖子,但沒有結論。 我嘗試了所有3個解決方案張貼here。 可能工作的解決方案是: - 解決方案1: 使用ClientCertRequestHandler反正(它標記爲隱藏,但顯然仍然可用):Android Webview客戶端證書,相互身份驗證,Web視圖上的SSL

所以我修改了的android.jar包括用於覆蓋onReceivedClientCertRequest內部API() 但我沒有得到在運行時的回調。任何第三方瀏覽器都是如此。我試圖在標準瀏覽器中加載相同的網頁。我在UI上得到了一個回調,要求用戶選擇一個客戶端證書。

因此,似乎只有系統瀏覽器應用程序可以從Webkit獲取onReceivedClientCertRequest()的回調。

在iOS平臺的情況下,Webview無法直接加載該網站。但是使用NSURL進行HTTPS連接, 會將客戶端證書保留在內存中一段時間​​,Webview可以成功加載此頁面。

在Android上,我已通過註冊SSLSocketFactory加載客戶端和服務器證書成功地設置了HTTPS通信。 我可以使用它來做REST API調用。但是與iOS不同的是,我無法找到Android webview可以使用客戶端證書進行相互驗證的方式。

我認爲通過Web視圖進行相互認證應該被平臺支持作爲安全性的基本要求之一。這個問題有沒有更新?

編輯1

我得到了它在Android 4.0工作,4.3按下面給出我的答案。 Hoverer,現在在Android 4.4上,似乎WebViewClientClassicExt類本身被刪除。 任何想法在這種情況下可以做什麼?爲什麼Android不允許在webview中設置ClientCertificates?

回答

3

,所以我可以讓這件事工作,直到4.3

  1. 在Android 4.0和4.1,通過擴展WebViewClient
  2. 一類在4.2,4.3的覆蓋onReceivedClientCertRequest()的一類重寫onReceivedClientCertRequest()擴展WebViewClientClassicExt。

我設置了私鑰和證書ClientCertRequestHandler的proceed()方法。

需要從Android上修復補丁爲4.4及以上

EDITED 解uptil 4.3以下給出

WebviewClientCustom.java

public class WebViewClientCustom extends WebViewClient { 
    private X509Certificate[] certificatesChain; 
    private PrivateKey clientCertPrivateKey; 
    private IWebViewCallbacks webviewCallbacks; 

    public WebViewClientCustom(IWebViewCallbacks webviewCallbacks) { 
     this.webviewCallbacks = webviewCallbacks; 
    } 

    public void onReceivedClientCertRequest(WebView paramWebView, 
      ClientCertRequestHandler paramClientCertRequestHandler, 
      String paramString) { 
     PrivateKey localPrivateKey = this.clientCertPrivateKey; 
     X509Certificate[] arrayOfX509Certificate = this.certificatesChain; 
     paramClientCertRequestHandler.proceed(localPrivateKey, 
       arrayOfX509Certificate); 
    } 

    public void onReceivedError(WebView view, int errorCode, 
      String description, String failingUrl) { 
     webviewCallbacks.onReceivedError(view, errorCode, 
       description, failingUrl); 

     super.onReceivedError(view, errorCode, 
       description, failingUrl); 
    } 


    public void setClientCertificate(PrivateKey paramPrivateKey, 
      X509Certificate[] paramArrayOfX509Certificate) { 
     this.clientCertPrivateKey = paramPrivateKey; 
     this.certificatesChain = paramArrayOfX509Certificate; 
    } 

    public boolean shouldOverrideUrlLoading(WebView paramWebView, 
      String paramString) { 
     return webviewCallbacks.shouldOverrideUrlLoading(paramWebView, 
       paramString); 


    } 

    @Override 
    public void onPageStarted(WebView view, String url, Bitmap favicon) { 
     // TODO Auto-generated method stub 

     webviewCallbacks.onPageStarted(view, url, favicon); 
     super.onPageStarted(view, url, favicon); 
    } 

    @Override 
    public void onPageFinished(WebView view, String url) { 
     // TODO Auto-generated method stub 

     webviewCallbacks.onPageFinished(view, url); 
     super.onPageFinished(view, url); 
    } 

} 

WebViewClientCustomExt。java的

public class WebViewClientCustomExt extends WebViewClientClassicExt { 
    private X509Certificate[] certificatesChain; 
    private PrivateKey clientCertPrivateKey; 
    private IWebViewCallbacks webviewCallbacks; 

    public WebViewClientCustomExt(IWebViewCallbacks webviewCallbacks) { 
     this.webviewCallbacks = webviewCallbacks; 
    } 

    public void onReceivedClientCertRequest(WebView paramWebView, 
      ClientCertRequestHandler paramClientCertRequestHandler, 
      String paramString) { 
     PrivateKey localPrivateKey = this.clientCertPrivateKey; 
     X509Certificate[] arrayOfX509Certificate = this.certificatesChain; 
     paramClientCertRequestHandler.proceed(localPrivateKey, 
       arrayOfX509Certificate); 
    } 

    public void onReceivedError(WebView view, int errorCode, 
      String description, String failingUrl) { 
     webviewCallbacks.onReceivedError(view, errorCode, 
       description, failingUrl); 

     super.onReceivedError(view, errorCode, 
       description, failingUrl); 
    } 



    public void setClientCertificate(PrivateKey paramPrivateKey, 
      X509Certificate[] paramArrayOfX509Certificate) { 
     this.clientCertPrivateKey = paramPrivateKey; 
     this.certificatesChain = paramArrayOfX509Certificate; 
    } 

    public boolean shouldOverrideUrlLoading(WebView paramWebView, 
      String paramString) { 
     return webviewCallbacks.shouldOverrideUrlLoading(paramWebView, paramString); 
    } 

    @Override 
    public void onPageStarted(WebView view, String url, Bitmap favicon) { 
     // TODO Auto-generated method stub 


     webviewCallbacks.onPageStarted(view, url, favicon); 
     super.onPageStarted(view, url, favicon); 
    } 

    @Override 
    public void onPageFinished(WebView view, String url) { 
     // TODO Auto-generated method stub 

     webviewCallbacks.onPageFinished(view, url); 
     super.onPageFinished(view, url); 
    } 
} 

使用

*/ 
    private void setCertificateData() { 
     // TODO Auto-generated method stub 
     try { 
      KeyStore clientCertKeystore = KeyStore.getInstance("pkcs12"); 
      String clientCertPkcsPassword = getPkcsPassword(); 
      byte[] pkcs12; 

      pkcs12 = getAuthP12Data(); 
      ByteArrayInputStream pkcs12BAIS = new ByteArrayInputStream(pkcs12); 

      clientCertKeystore.load(pkcs12BAIS, 
        clientCertPkcsPassword.toCharArray()); 
      String alias = (clientCertKeystore.aliases().nextElement()); 
      Certificate[] arrayOfCertificate = clientCertKeystore 
        .getCertificateChain(alias); 
      X509Certificate[] arrayOfX509Certificate = new X509Certificate[arrayOfCertificate.length]; 
      for (int i = 0; i < arrayOfCertificate.length; i++) { 
       arrayOfX509Certificate[i] = (X509Certificate) arrayOfCertificate[i]; 
      } 
      PrivateKey localPrivateKey = (PrivateKey) clientCertKeystore 
        .getKey(alias, clientCertPkcsPassword.toCharArray()); 
      if (android.os.Build.VERSION.SDK_INT <= 16) { 
       WebViewClientCustom webvviewClient = new WebViewClientCustom(
         myWebViewClient); 
       webvviewClient.setClientCertificate(localPrivateKey, 
         arrayOfX509Certificate); 
       webView.setWebViewClient(webvviewClient); 

      } else { 
       WebViewClientCustomExt webvviewClient = new WebViewClientCustomExt(
         myWebViewClient); 
       webvviewClient.setClientCertificate(localPrivateKey, 
         arrayOfX509Certificate); 
       webView.setWebViewClient(webvviewClient); 
      } 
      // webView.getSettings().setJavaScriptEnabled(true); 

     } catch (Exception e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

    } 
+0

我有2個查詢此答案。一。方法在API Level 21(Lolipop)中添加了方法WebViewClient.onReceivedClientCertRequest(),但是您說在Android 4.0和4.1上使用了此方法。第二。您是否找到Android 4.4及以上API級別的解決方案?請回復? –

+0

Sagar我已經更新了第一部分的答案。我沒有檢查4.4以上的解決方案。 –

+0

嗨,我必須這樣做,但私鑰是在一個密碼令牌中。我可以使用它嗎? – Indio

相關問題