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