WebView loadUrl()中的信任证书颁发机构 [英] Trust Certificate Authority in WebView loadUrl()

查看:321
本文介绍了WebView loadUrl()中的信任证书颁发机构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从安全扫描程序的结果来看,我需要限制应用程序信任的证书颁发机构.

From a result of security scan program, I have a need to restrict the Certificate Authorities the app trusts.

扫描结果指出webView.loadUrl("https://example.com/page");处的线.我看到了如何创建一个使用TrustManager的SslSocketFactory的方法,但是在WebView中没有看到允许我进行设置的API.

The scan result points out the line at webView.loadUrl("https://example.com/page");. I see how I can create a SslSocketFactory that uses my TrustManager, but I don't see an API in WebView that allows me to set that.

https://developer.android.com/training/articles/security-ssl.html#UnknownCa

有哪些可能的方法来实现这一目标?

What are some possible ways to achieve this?

推荐答案

我认为WebViewClientonReceivedSslError方法将是一个很好的切入点.

I think WebViewClient 's onReceivedSslError method will be a good entry point.

首先,遵循 https://developer.android.com/training/articles/security-ssl.html#UnknownCa 来准备TrustManager.

First of all, follow the exact same snippet from https://developer.android.com/training/articles/security-ssl.html#UnknownCa to prepare TrustManager.

    TrustManagerFactory tmf = null;

    private void initTrustStore() throws
            java.security.cert.CertificateException, FileNotFoundException,
            IOException, KeyStoreException, NoSuchAlgorithmException {

        // Create a KeyStore containing our trusted CAs
        String keyStoreType = KeyStore.getDefaultType();
        KeyStore trustedKeyStore = KeyStore.getInstance(keyStoreType);
        trustedKeyStore.load(null, null);

        CertificateFactory cf = CertificateFactory.getInstance("X.509");

        InputStream caInput = new BufferedInputStream(
                    getResources().getAssets().open("ca.crt"));
            Certificate ca;
            try {
                ca = cf.generateCertificate(caInput);
                Log.d(TAG, "ca-root DN=" + ((X509Certificate) ca).getSubjectDN());
            }
            finally {
                caInput.close();
            }
            trustedKeyStore.setCertificateEntry("ca", ca);

        // Create a TrustManager that trusts the CAs in our KeyStore
        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init(trustedKeyStore);

    }

然后,扩展自定义WebViewClient类,检查 https://stackoverflow.com/a/6379434/1099884 中的代码段

Then, extends custom WebViewClient class, checking snippet from https://stackoverflow.com/a/6379434/1099884

private class CheckServerTrustedWebViewClient extends WebViewClient{
    public void onReceivedSslError(WebView view, final SslErrorHandler handler, SslError error) {
        Log.d(TAG, "onReceivedSslError");
        boolean passVerify = false;

        if(error.getPrimaryError() == SslError.SSL_UNTRUSTED){
            SslCertificate cert = error.getCertificate();
            String subjectDN = cert.getIssuedTo().getDName();
            Log.d(TAG, "subjectDN: "+subjectDN);
            try{
                Field f = cert.getClass().getDeclaredField("mX509Certificate");
                f.setAccessible(true);
                X509Certificate x509 = (X509Certificate)f.get(cert);

                X509Certificate[] chain = {x509};
                for (TrustManager trustManager: tmf.getTrustManagers()) {
                    if (trustManager instanceof X509TrustManager) {
                        X509TrustManager x509TrustManager = (X509TrustManager)trustManager;
                        try{
                            x509TrustManager.checkServerTrusted(chain, "generic");
                            passVerify = true;break;
                        }catch(Exception e){
                            Log.e(TAG, "verify trustManager failed", e);
                            passVerify = false;
                        }
                    }
                }
                Log.d(TAG, "passVerify: "+passVerify);
            }catch(Exception e){
                Log.e(TAG, "verify cert fail", e);
            }
        }
        if(passVerify == true)handler.proceed();
        else handler.cancel();

    }       

}

最后,将CheckServerTrustedWebViewClient设置为WebView

webView.setWebViewClient(new CheckServerTrustedWebViewClient());

但是,有一个问题.准备好的CA证书是服务器证书的唯一证书(中间CA而非根CA).仅提供根CA证书将不起作用. TrustManager不能在运行时下载服务器证书链吗?有什么建议吗?

However, there is one problem. The prepared CA certificate is the exact one sign the server one (intermediate-CA NOT root CA). Only provide root CA certificate will not work. Isn't TrustManager can download server certificate chain on runtime? Any suggestion?

这篇关于WebView loadUrl()中的信任证书颁发机构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆