Доверительный центр сертификации в WebView loadUrl()

В результате сканирования программы безопасности мне нужно ограничить центры сертификации, которым доверяет приложение.

Результат сканирования указывает на строку в webView.loadUrl("https://example.com/page");, Я вижу, как я могу создать SslSocketFactory, который использует мой TrustManager, но я не вижу API в WebView, который позволил бы мне установить это.

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

Каковы возможные пути достижения этого?

2 ответа

Я думаю WebViewClient "s onReceivedSslError Метод будет хорошей отправной точкой.

Прежде всего, следуйте тому же фрагменту из https://developer.android.com/training/articles/security-ssl.html чтобы подготовить 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, проверяя фрагмент из /questions/44556059/proverka-sertifikatov-x509-s-ispolzovaniem-java-apis/44556068#44556068

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 не может загружать цепочку сертификатов сервера во время выполнения? Любое предложение?

Документ , похоже , обновлен:

К счастью, вы можете научить свое приложение доверять пользовательским центрам сертификации, настроив конфигурацию сетевой безопасности вашего приложения без необходимости изменять код внутри вашего приложения.

сообщение в блоге, я думаю, связано

Другие вопросы по тегам