web-dev-qa-db-fra.com

Gestion des erreurs de certificat dans Android Webview et suppression des préférences de certificat

J'essaie de trouver un moyen approprié de gérer les erreurs de certificat SSL dans la vue Web Android. Mon objectif est de fournir un moyen de charger les pages avec des erreurs de certificat SSL, mais laissez l'utilisateur choisir de charger la page après l'avoir averti. à propos de la sécurité chaque fois qu'il essaie de charger une URL avec des erreurs de certificat .

Les solutions les plus proches que j'ai trouvées dans les discussions suggèrent de remplacer le WebViewClient comme suit:

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

Cependant, cela désactive fondamentalement SSL dans WebView sans le consentement de l'utilisateur.

Pour référence, voici les discussions où j'ai trouvé cette solution:

Android WebView SSL 'Avertissement de sécurité'

Web View sur Android prend-il en charge SSL?

Android WebView ne charge pas une URL HTTPS

Webview Android avec certificat client

La vue Web affiche une page blanche/blanche après le chargement de l'URL lors de l'utilisation de WIFI sous Android

Impossible de charger une page Web spécifique sur la vue Web Android

WebView affiche une vue vierge pour certains liens

Android WebView bloque la redirection de https vers http

Ignorer les demandes de certificats SSL dans la visualisation Web

Je suis allé de l'avant et ai implémenté une version légèrement différente qui invite l'utilisateur:

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

Cette implémentation demande deux fois à l'utilisateur s'il veut charger la page, s'il dit oui deux fois, l'erreur est ignorée et la page est chargée, sinon le chargement de la page est annulé.

La première fois qu'une URL avec une erreur de certificat est chargée, WebViewClient.onReceivedSslError est appelé. Toutefois, si l'utilisateur continue avec l'erreur de certificat et que SslErrorHandler.proceed() est appelé, les temps suivants où la même URL est chargée, WebViewClient.onReceivedSslError n'est jamais appelé à nouveau: le seul fait de supprimer l'application résout ce problème.

Je voudrais que WebViewClient.onReceivedSslError soit appelé systématiquement lorsqu’une URL avec une erreur de certificat se charge, pas seulement la première fois. J'ai essayé d'appeler ces méthodes sans succès:

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

Est-ce que quelqu'un sait comment appeler WebView WebViewClient.onReceivedSslError plusieurs fois pour la même URL après l'appel de SslErrorHandler.proceed()?

14
androidseb

Ne jamais remplacer la méthode onReceivedSslError. Google Play refusera votre envoi de la manière la plus intelligente est de gérer l'utilisation des erreurs SSL webSettings.setDomStorageEnabled(true);

3
Chinthaka Devinda

Oui, vous pouvez utiliser clearSslPreferences () comme ici:

webView.clearSslPreferences()

Ça va effacer votre décision pour cet objet de WebView

1
Djek-grif

Je vais simplement publier la réponse que Tssomas a donnée dans les commentaires de la question initiale, car après tout ce temps, c'est la seule solution qui fonctionne de manière fiable, même si c'est un bidouillage.

Citant Tssomas:

Si l'utilisateur continue, sa préférence pour continuer de toute façon n'est conservée que Pour cette session (s'il ferme l'application et la redémarre, la boîte de dialogue Réapparaîtra). Donc, ce que j’ai fait pour que l’utilisateur voie la boîte de dialogue À chaque fois a été d’ajouter l’URL non sécurisée à une liste de tableaux et d’ajouter une vérification De sorte que chaque fois que la vue Web se charge complètement, la liste de tableaux est cochée pour l'URL actuelle de la webview. Alors, bien sûr, si la liste de tableaux Contient l’URL actuelle, affichez la boîte de dialogue .. ce n’est pas une jolie solution Mais ça fonctionne ...

Voici à quoi pourrait ressembler le code ...

//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