web-dev-qa-db-ja.com

Android Webviewでの証明書エラーの処理と証明書設定のクリア

Android WebviewでSSL証明書エラーを処理する適切な方法を見つけようとしています。私の目標は、SSL証明書エラーのあるページをロードする方法を提供することですが、ユーザーがセキュリティについて警告した後のページ証明書エラーのあるURLをロードしようとするとき

スレッドで見つけた最も近いソリューションは、次のようにWebViewClientをオーバーライドすることをお勧めします。

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

ただし、これは基本的にユーザーの同意なしにWebViewのSSLを無効にします。

参考までに、私がその解決策を見つけたスレッドを次に示します。

Android WebView SSL「セキュリティ警告」

Android SSLをサポートしていますか?

Android WebViewがHTTPS URLをロードしない

クライアント証明書付きのAndroid WebView

AndroidでWIFIを使用している場合、URLのロード後にWebビューに空白/白いページが表示されます

Android webview で特定のWebページをロードできません

WebViewは特定のリンクに対して空白のビューを表示します

Android WebViewはhttpsからhttpへのリダイレクトをブロックします

webviewで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();
                }
            });
    }
});
_

この実装は、ページをロードするかどうかをユーザーに2回尋ねます。yesを2回言うと、エラーは無視されてページがロードされます。それ以外の場合、ページのロードはキャンセルされます。

証明書エラーのあるURLが初めて読み込まれると_WebViewClient.onReceivedSslError_が呼び出されますが、ユーザーが証明書エラーを続行してSslErrorHandler.proceed()が呼び出されると、同じURLが読み込まれると_WebViewClient.onReceivedSslError_が再び呼び出されることはありません。アプリを強制終了するだけでこの動作がリセットされます。

初めてではなく、証明書エラーのあるURLが読み込まれたときに_WebViewClient.onReceivedSslError_が体系的に呼び出されるようにしたいと思います。私は成功せずにそれらのメソッドを呼び出してみました:

_/** 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();
_

SslErrorHandler.proceed()が呼び出された後、同じURLに対してWebView呼び出し_WebViewClient.onReceivedSslError_を複数回行う方法を誰かが知っていますか?

16
androidseb

OnReceivedSslErrorメソッドをオーバーライドしないでください。 Google Playはアップロードを拒否します。最も賢い方法はSSLエラーを処理することですwebSettings.setDomStorageEnabled(true);

6

はい、次のようにclearSslPreferences()を使用できます。

webView.clearSslPreferences()

WebViewのこのオブジェクトに対する決定をクリアします

2
Djek-Grif

Tssomasが元の質問のコメントで提供した答えを投稿します。これは結局のところ、それがハックであっても確実に機能する唯一のソリューションだからです。

Tssomasの引用:

ユーザーが続行すると、先に進むという彼らの好みはそのセッションの間のみ維持されます(ユーザーがアプリを閉じて再度起動した場合、ダイアログが再表示されます)。したがって、ユーザーがダイアログを毎回確実に表示するために行ったのは、セキュリティで保護されていないURLを配列リストに追加し、Webビューの読み込みが完了するたびに配列リストのWebビューの現在のURLがチェックされるようにチェックを追加することでした。したがって、もちろん、配列リストに現在の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);
    }
});
0
androidseb