0

我的應用使用https來conncet到服務器,對於使用自簽名證書的服務器,webview將調用其onReceivedSslError方法。我需要回應回調並顯示一個可見的對話框來顯示證書信息,特別是sha1和sha256指紋。但我感到非常困惑,因爲SslCertificate不支持任何getFingerprint方法。有任何想法嗎?當webview onReceivedSslError被調用時,如何獲取證書指紋

onReceivedSslError方法如下所示。

@Override 
    public void onReceivedSslError(WebView view, final SslErrorHandler handler, SslError error) { 
     Log.d(DEBUG_TAG, "onReceivedSslError " + error.getCertificate().toString()); 
     // error.getCertificate().getSha1FingerPrint(); is not available 
     // below methods are available 
     // error.getCertificate().getIssuedBy(); 
     // error.getCertificate().getIssuedTo(); 
     // error.getCertificate().getValidNotAfterDate(); 
     // error.getCertificate().getValidNotBeforeDate(); 
     // error.getUrl(); 
     if (error.getPrimaryError() == SslError.SSL_UNTRUSTED) { 
      final Account account = new Account(serverUrl, null, null); 
      SslConfirmDialog dialog = new SslConfirmDialog(account, 
        new SslConfirmDialog.Listener() { 
         @Override 
         public void onAccepted(boolean rememberChoice) { 
          CertsManager.instance().saveCertForAccount(account, rememberChoice); 
          // Ignore SSL certificate validate 
          handler.proceed(); 
         } 

         @Override 
         public void onRejected() { 
          displaySSLError(); 
         } 
        }); 
      dialog.show(getSupportFragmentManager(), SslConfirmDialog.FRAGMENT_TAG); 
      return; 
     } 

    } 

回答

2

你可以做這樣的事情讓X509證書

public void onReceivedSslError(WebView view, SslErrorHandler handler, 
     SslError error) { 
    Bundle bundle = SslCertificate.saveState(error.getCertificate()); 
    X509Certificate certificate; 
    byte[] bytes = bundle.getByteArray("x509-certificate"); 
    if (bytes == null) { 
     certificate = null; 
    } else { 
     try { 
      CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); 
      Certificate cert = certFactory.generateCertificate(new ByteArrayInputStream(bytes)); 
      certificate = (X509Certificate) cert; 
     } catch (CertificateException e) { 
      certificate = null; 
     } 
    } 
} 

一旦你的X509證書,你可以使用x509證書的的getEncoded()API獲取指紋。

禮貌:http://grepcode.com/file/repo1.maven.org/maven2/org.robolectric/android-all/4.3_r2-robolectric-0/android/net/http/SslCertificate.java#SslCertificate.restoreState%28android.os.Bundle%29

0

SslCertificate類不具有潛在的x509證書一個公共的getter,我們只能通過黑客做到這一點。這隻適用於andorid 4.0+。所以我通過下面的一些小問題解決了這個問題。

/** 
* SslCertificate class does not has a public getter for the underlying 
* X509Certificate, we can only do this by hack. This only works for andorid 4.0+ 
* @see https://groups.google.com/forum/#!topic/android-developers/eAPJ6b7mrmg 
*/ 
public static X509Certificate getX509CertFromSslCertHack(SslCertificate sslCert) { 
    X509Certificate x509Certificate = null; 

    Bundle bundle = SslCertificate.saveState(sslCert); 
    byte[] bytes = bundle.getByteArray("x509-certificate"); 

    if (bytes == null) { 
     x509Certificate = null; 
    } else { 
     try { 
      CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); 
      Certificate cert = certFactory.generateCertificate(new ByteArrayInputStream(bytes)); 
      x509Certificate = (X509Certificate) cert; 
     } catch (CertificateException e) { 
      x509Certificate = null; 
     } 
    } 

    return x509Certificate; 
}