Подтвердить что ты не робот

Обработка ошибок сертификата в Android Webview и очистка сертификатов

Я пытаюсь найти правильный способ обработки ошибок сертификата SSL в Android Webview. Моя цель - предоставить способ загрузки страниц с ошибками сертификата SSL, но пусть пользователь решит загрузить страницу после предупреждения о безопасности при попытке загрузить URL-адрес с ошибками сертификата.. p >

Ближайшие решения, которые я нашел в потоках, предлагают переопределить WebViewClient следующим образом:

webView.setWebViewClient(new WebViewClient() {
    @Override
    public void onReceivedSslError(final WebView view, final SslErrorHandler handler, final SslError error) {
        handler.proceed();
    }
});

Однако это в основном отключает SSL в WebView без согласия пользователя.

Для справки приведены темы, в которых я нашел это решение:

Предупреждение безопасности Android WebView SSL

Поддерживает ли веб-представление на Android поддержку SSL?

Android WebView не загружает URL HTTPS

веб-просмотр android с сертификатом клиента

Веб-представление показывает пустую/белую страницу после загрузки URL-адреса при использовании WIFI в Android

Невозможно загрузить определенную веб-страницу в веб-браузере Android

WebView отображает пустой вид для определенных ссылок

Android WebView блокирует перенаправление с https на http

Игнорировать запросы сертификата ssl в веб-браузере

Я пошел вперед и внедрил немного другую версию, которая подсказывает пользователю:

webView.setWebViewClient(new WebViewClient() {
    @Override
    public void onReceivedSslError(final WebView view, final SslErrorHandler handler, final SslError error) {
        //Showing a first confirmation dialog
        AndroidUtils.showYesNoDialog(
            //First confirmation message
            "WARNING - THIS PAGE IS NOT SECURE! Are you sure you want to continue loading it?",
            //First confirmation "YES" option runnable
            new Runnable() {
                @Override
                public void run() {
                    //Showing a second confirmation dialog
                    AndroidUtils.showYesNoDialogWithResId(
                        //Second confirmation message
                        "You chose to load an unsecure page, are you sure you want to do that?",
                        //Second confirmation "YES" option runnable
                        new Runnable() {
                            @Override
                            public void run() {
                                //Disregard the error and proceed with the bad certificate anyways
                                handler.proceed();
                            }
                        },
                        //Second confirmation "NO" option runnable
                        new Runnable() {
                            @Override
                            public void run() {
                                //Cancel loading the page with that certificate error
                                handler.cancel();
                            }
                        }
                    );
                }
            },
            //First confirmation "NO" option runnable
            new Runnable() {
                @Override
                public void run() {
                    //Cancel loading the page with that certificate error
                    handler.cancel();
                }
            });
    }
});

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

В первый раз, когда URL-адрес с загрузкой сертификатов загружается, WebViewClient.onReceivedSslError вызывается, однако, если пользователь отправляется с ошибкой сертификата и вызывается SslErrorHandler.proceed(), то при загрузке одного и того же URL-адреса WebViewClient.onReceivedSslError больше не вызывается: только убийство приложения сбрасывает это поведение.

Я бы хотел, чтобы WebViewClient.onReceivedSslError назывался систематически, когда URL-адрес с ошибкой сертификата загружается не только в первый раз. Я пробовал эти методы без успеха:

/** JAVADOC QUOTE: Clears the SSL preferences table stored in response to proceeding with SSL certificate errors.*/
webView.clearSslPreferences();
//Those other methods I tried out of despair just in case
webView.clearFormData();
webView.clearCache(true);
webView.clearHistory();
webView.clearMatches();

Кто-нибудь знает, как сделать вызов WebView WebViewClient.onReceivedSslError более одного раза для одного и того же URL-адреса после того, как SslErrorHandler.proceed() был вызван?

4b9b3361

Ответ 1

Никогда не переопределяйте метод onReceivedSslError. Игра Goole будет отклонять ваш самый загруженный способ загрузки, чтобы обрабатывать использование ошибок SSL webSettings.setDomStorageEnabled(true);

Ответ 2

Да, вы можете использовать clearSslPreferences(), как здесь:

webView.clearSslPreferences()

Он очистит ваше решение для этого объекта WebView

Ответ 3

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

Цитирование Tssomas:

Если пользователь продолжит, их предпочтение идти вперед в любом случае сохраняется только для этого сеанса (если они закрывают приложение и снова запускают его диалог будет повторное шоу). Так что я сделал, чтобы убедиться, что пользователь видит диалог каждый раз приходилось добавлять небезопасный URL-адрес в список массивов и добавлять проверьте, чтобы каждый раз, когда веб-просмотр заканчивает загрузку, список массивов проверяется на текущий URL-адрес webview. Поэтому, конечно, если список массивов содержит текущий URL-адрес, показывает диалог.. его не довольно решение, но оно работает...

Вот как выглядит код...

//This has to be static because it will be reset only once the app process is killed
private static final Set<String> unsecureURLSet = new TreeSet<>();

webView.setWebViewClient(new WebViewClient() {
    @Override
    public void onReceivedSslError(final WebView view, final SslErrorHandler handler, final SslError error) {
        //Adding the insecure URL to the set
        unsecureURLSet.add(error.getUrl());
        //Showing a first confirmation dialog
        AndroidUtils.showYesNoDialog(
            //First confirmation message
            "WARNING - THIS PAGE IS NOT SECURE! Are you sure you want to continue loading it?",
            //First confirmation "YES" option runnable
            new Runnable() {
                @Override
                public void run() {
                    //Showing a second confirmation dialog
                    AndroidUtils.showYesNoDialogWithResId(
                        //Second confirmation message
                        "You chose to load an unsecure page, are you sure you want to do that?",
                        //Second confirmation "YES" option runnable
                        new Runnable() {
                            @Override
                            public void run() {
                                //Disregard the error and proceed with the bad certificate anyways
                                handler.proceed();
                            }
                        },
                        //Second confirmation "NO" option runnable
                        new Runnable() {
                            @Override
                            public void run() {
                                //Cancel loading the page with that certificate error
                                handler.cancel();
                            }
                        }
                    );
                }
            },
            //First confirmation "NO" option runnable
            new Runnable() {
                @Override
                public void run() {
                    //Cancel loading the page with that certificate error
                    handler.cancel();
                }
            });
    }

    @Override
    public boolean shouldOverrideUrlLoading(final WebView _view, final String _url) {
        if (unsecureURLSet.contains(_url)){
            //Code here should mimic the dialog in onReceivedSslError
            //And replace the "handler.proceed()" with a forced load of _url
            return true;
        }
        return super.shouldOverrideUrlLoading(_view, _url);
    }
});