Android WebView ne charge pas une URL HTTPS

91
public void onCreate(Bundle savedInstance)
{       
    super.onCreate(savedInstance);
    setContentView(R.layout.show_voucher);
    webView=(WebView)findViewById(R.id.webview);
    webView.getSettings().setJavaScriptEnabled(true);
    webView.getSettings().setBuiltInZoomControls(true);
    String url ="https://www.paymeon.com/Vouchers/?v=%C80%8D%B1x%D9%CFqh%FA%84%C35%0A%1F%CE&iv=%25%EE%BEi%F4%DAT%E1"
    //webView.loadUrl(url); // Not Working... Showing blank
    webView.loadUrl("http://www.yahoo.com"); // its working    
}

Lorsque j'essaye de charger une URL dans WebBView, il n'affiche qu'un écran vide. Si je charge Google.com ou yahoo.com, cela fonctionne bien.

sumit
la source
1
ça marche j'ai vérifié maintenant. vérifiez à nouveau si cela ne fonctionne pas après cela, ajoutez-le avec votre code webView.getSettings (). setUseWideViewPort (true); webView.getSettings (). setLoadWithOverviewMode (true);
ilango j

Réponses:

154

Veuillez visiter ce lien:

Ajoutez cette méthode de substitution à votre implémentation WebViewClient. Vous devrez le compiler avec Android SDK 2.2 (API niveau 8) ou version ultérieure. La méthode apparaît dans le SDK public à partir de la version 2.2 (API niveau 8) mais nous l'avons testée sur des appareils exécutant 2.1, 1.6 et 1.5 et elle fonctionne également sur ces appareils (donc évidemment, le comportement a toujours été là).

 @Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
    handler.proceed(); // Ignore SSL certificate errors
}

cela vous aidera.

Fargath
la source
3
La dernière entrée de la discussion a très bien fonctionné. Merci beaucoup.
Bill Lahti
54
Avertissement de sécurité : notez que cela va complètement à l'encontre de l'objectif d'avoir SSL en premier lieu.
ereOn
8
Veuillez ne pas faire ça. Ce n'est pas sécurisé et n'est pas autorisé dans le Play Store.
Antimoine
33
Google envoie maintenant des e-mails à quiconque met en œuvre la solution ci-dessus:Your app(s) listed at the end of this email have an unsafe implementation of the WebViewClient.onReceivedSslError handler. Specifically, the implementation ignores all SSL certificate validation errors, making your app vulnerable to man-in-the-middle attacks. Apps with vulnerabilities that expose users to risk of compromise may be considered Dangerous Products in violation of the Content Policy and section 4.4 of the Developer Distribution Agreement.
Gustavo
3
Tout le monde sait comment résoudre l'avertissement de sécurité Google, si oui, veuillez me le faire savoir car je suis également confronté à ce problème.
Pratik Tank
48

Par bonne réponse de fargth, voici un petit exemple de code qui pourrait vous aider.

Tout d'abord, créez une classe qui étend WebViewClient et qui est définie pour ignorer les erreurs SSL:

// SSL Error Tolerant Web View Client
private class SSLTolerentWebViewClient extends WebViewClient {

            @Override
            public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
                handler.proceed(); // Ignore SSL certificate errors
            }

}

Ensuite, avec votre objet de vue Web (initié dans la méthode OnCreate ()), définissez son client de vue Web comme une instance de la classe de remplacement:

 mWebView.setWebViewClient(
                new SSLTolerentWebViewClient()
        );
Robnick
la source
2
cela donne l'avertissement de sécurité google: implémentation non sécurisée du gestionnaire WebViewClient.onReceivedSslError. savez-vous comment résoudre ce problème?
Pratik Tank
2
Google a marqué l'application comme non conforme sur Playstore, comment le faire sans SSL?
Ajay Pandya
N'utilisez pas la méthode Super - super.onReceivedSslError (vue, gestionnaire, erreur);
Atul Bhardwaj
40

Pour gérer correctement la validation du certificat SSL et éviter le rejet d'application de Google conformément à la nouvelle politique de sécurité, modifiez votre code pour appeler SslErrorHandler.proceed () chaque fois que le certificat présenté par le serveur répond à vos attentes, et appelez SslErrorHandler.cancel () dans le cas contraire.

Par exemple, j'ajoute une boîte de dialogue d'alerte pour que l'utilisateur ait confirmé et semble que Google n'affiche plus d'avertissement.

    @Override
    public void onReceivedSslError(WebView view, final SslErrorHandler handler, SslError error) {
    final AlertDialog.Builder builder = new AlertDialog.Builder(this);
    String message = "SSL Certificate error.";
        switch (error.getPrimaryError()) {
            case SslError.SSL_UNTRUSTED:
                message = "The certificate authority is not trusted.";
                break;
            case SslError.SSL_EXPIRED:
                message = "The certificate has expired.";
                break;
            case SslError.SSL_IDMISMATCH:
                message = "The certificate Hostname mismatch.";
                break;
            case SslError.SSL_NOTYETVALID:
                message = "The certificate is not yet valid.";
                break;
        }
        message += " Do you want to continue anyway?";

        builder.setTitle("SSL Certificate Error");
        builder.setMessage(message);
    builder.setPositiveButton("continue", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            handler.proceed();
        }
    });
    builder.setNegativeButton("cancel", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            handler.cancel();
        }
    });
    final AlertDialog dialog = builder.create();
    dialog.show();
}

Après ces changements, il n'affichera pas d'avertissement.

Anant Shah
la source
que se passera-t-il si j'ai supprimé le bloc onReceivedSslError de l'implémentation?
Vivek Sinha
1
@VivekSinha il appellera handler.cancel (); par défaut.
Anant Shah
1
mais Google a toujours rejeté mon application en disant la même raison. Pourquoi?
Vivek Sinha
@VivekSinha a-t-il trouvé une solution concernant le lancement de l'application dans le Play Store?
Kesha
2
J'ai implémenté le rappel onReceivedSslError comme suggéré. L'application a été publiée avec succès par la suite.
Vivek Sinha
11

Supprimez le code ci-dessous, cela fonctionnera

 super.onReceivedSslError(view, handler, error);
Roi des messes
la source
Super, cela a fonctionné pour moi. Pouvez-vous expliquer comment cela a fonctionné?
Arth Tilva
3
@ArthTilva de la documentation google: "le comportement par défaut est d'annuler le chargement". En appelant super, vous appelez ce comportement par défaut avant qu'il ne puisse atteindre le reste de la méthode. developer.android.com/reference/android/webkit/…
Josh Laird
11

remplacer onReceivedSslError et supprimer

super.onReceivedSslError (vue, gestionnaire, erreur)

Et pour résoudre la sécurité de Google:

setDomStorageEnabled (vrai);

Le code complet est:

webView.enableJavaScript();
webView.getSettings().setDomStorageEnabled(true); // Add this
webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
webView.setWebViewClient(new WebViewClient(){
        @Override
        public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
            // DO NOT CALL SUPER METHOD
            super.onReceivedSslError(view, handler, error);
        }
    });
FarshidABZ
la source
Merci beaucoup mec. La suppression de super.onReceivedSslError (vue, gestionnaire, erreur) a fonctionné pour moi.
Däñish Shärmà
7

Copiez et collez votre ligne de code bro, cela fonctionnera croyez-moi :) Je pense que vous obtenez une erreur ssl. Si vous utilisez la méthode override onReceivedSslError et supprimez super c'est la super méthode. Écrivez simplement handler.proceed (), l'erreur résoudra.

    webView.setWebChromeClient(new WebChromeClient() {
        public void onProgressChanged(WebView view, int progress) {

            activity.setTitle("Loading...");
            activity.setProgress(progress * 100);

            if (progress == 100)
                activity.setTitle(getResources().getString(R.string.app_name));
        }
    });

    webView.setWebViewClient(new WebViewClient() {
        @Override
        public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
            Log.d("Failure Url :" , failingUrl);
        }

        @Override
        public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
            Log.d("Ssl Error:",handler.toString() + "error:" +  error);
            handler.proceed();
        }

        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            view.loadUrl(url);
            return true;
        }
    });
    webView.getSettings().setJavaScriptEnabled(true);
    webView.getSettings().setLoadWithOverviewMode(true);
    webView.getSettings().setUseWideViewPort(true);
    webView.getSettings().setDomStorageEnabled(true);
    webView.loadUrl(Constant.VIRTUALPOS_URL + "token=" + Preference.getInstance(getContext()).getToken() + "&dealer=" + Preference.getInstance(getContext()).getDealerCode());
ozanurkan
la source
Merci. Appelez handler.proceed () dans onReceivedSslErrorSave my day
Tam Huynh
2
Si vous faites cela (maintenant juillet 2019), Google Play rejettera votre candidature.
Alp Altunel du
J'ai trop d'applications sur Google Play, aucune application n'est toujours rejetée.
ozanurkan
1
rejettera janvier 2020 on-words
John Ruban Singh
6

Pour gérer les URL SSL, utilisez la méthode onReceivedSslError () de la classe WebViewClient, voici un exemple:

 webview.setWebViewClient(new WebViewClient() {
              ...
              ...
              ...

            @Override
            public void onReceivedSslError(WebView view, final SslErrorHandler handler, SslError error) {
                String message = "SSL Certificate error.";
                switch (error.getPrimaryError()) {
                    case SslError.SSL_UNTRUSTED:
                        message = "The certificate authority is not trusted.";
                        break;
                    case SslError.SSL_EXPIRED:
                        message = "The certificate has expired.";
                        break;
                    case SslError.SSL_IDMISMATCH:
                        message = "The certificate Hostname mismatch.";
                        break;
                    case SslError.SSL_NOTYETVALID:
                        message = "The certificate is not yet valid.";
                        break;
                }
                message += "\"SSL Certificate Error\" Do you want to continue anyway?.. YES";

                handler.proceed();
            }

        });

Vous pouvez consulter mon exemple complet ici: https://github.com/Jorgesys/Android-WebView-Logging

entrez la description de l'image ici

Jorgesys
la source
6

Pour résoudre la sécurité de Google, procédez comme suit:

Lignes vers le haut:

import android.webkit.SslErrorHandler;
import android.net.http.SslError;

Code:

class SSLTolerentWebViewClient extends WebViewClient {
    @Override
    public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
        if (error.toString() == "piglet")
            handler.cancel();
        else
            handler.proceed(); // Ignore SSL certificate errors
    }
}
Ronen
la source
2
Je suis nouveau sur Android. Où dois-je mettre ça? :)
Gediminas
5

J'ai suivi les réponses ci-dessus mais cela ne semble pas fonctionner pour moi ci-dessous, le code m'a fait un truc lors de l'intégration de passerelles de paiement qui sont généralement des requêtes https:

public class MainActivity extends Activity {

    WebView webView;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        webView = (WebView) findViewById(R.id.webView1);
        WebSettings settings = webView.getSettings();
        settings.setJavaScriptEnabled(true);
        settings.setDomStorageEnabled(true);
        webView.setWebViewClient(new MyWebViewClient());
        String postData = "amount=1000&firstname=mtetno&[email protected]&phone=2145635784&productinfo=android&surl=success.php"
                + "&furl=failure.php&lastname=qwerty&curl=dsdsd.com&address1=dsdsds&address2=dfdfd&city=dsdsds&state=dfdfdfd&"
                + "country=fdfdf&zipcode=123456&udf1=dsdsds&udf2=fsdfdsf&udf3=jhghjg&udf4=fdfd&udf5=fdfdf&pg=dfdf";
        webView.postUrl(
                "http://host/payment.php",
                EncodingUtils.getBytes(postData, "BASE64"));

    }

    private class MyWebViewClient extends WebViewClient {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            webView.loadUrl(url);
            return true;
        }

        @Override
        public void onReceivedSslError(WebView view, SslErrorHandler handler,
                SslError error) {
            handler.proceed();
        }
    }
}

Le code ci-dessus fait une demande de publication dans la vue Web et redirige vers la passerelle de paiement.

Le réglage a settings.setDomStorageEnabled(true);fait un tour pour moi J'espère que cela aide.

KOTIOS
la source
2
Cette solution désactive COMPLÈTEMENT la validation des certificats, vous laissant ouvert aux attaques man-in-the-middle. C'est quelque chose que vous ne devriez jamais faire, SURTOUT pour les passerelles de paiement.
Dirbaio
Pour moi, au départ, la vue Web ne chargeait pas le contenu, mais juste l'image d'arrière-plan de la page. Après que je viens de l'ajouter, webview.getSettings.setDomStorageEnabled(true);cela a fonctionné comme par magie. Peut-être que la page Web utilise une sorte d'API HTML 5, donc activer DomStorage a fonctionné pour moi.
Ishant Sagar
handler.proceed () contournant SSL
John Ruban Singh
qu'est-ce que Encodingutil.getbyte
Akash kumar
2

L'approche recommandée sera

1. N'appelez pas la méthode super (Supprimez l'appel super de la méthode remplacée)

2.Google recommande d'appeler la méthode SslErrorHandler.cancel () si une erreur survient

3. Ne pas demander de dialogue pour exposer les erreurs SSL

Quelle est la meilleure solution ?? Supprimer cette méthode de remplacement

@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler,SslError error) {

}
John Ruban Singh
la source
Demandez-vous une solution ou en suggérez-vous une?
Dharman
Je suggère cette approche
John Ruban Singh
@JohnRubanSingh Salut John, j'ai chargé un fichier JS à partir d'actifs et une fois le fichier chargé avec onPageFinished, j'appelle une fonction dans JS. Donc, remplacer onReceivedSslError () est nécessaire car j'utilise webview.setWebViewClient (nouveau ....)?
Shivam Sharma
Ce code rejetant mon APK.Même depuis 9 mois ce code ne provoque pas de rejet mais fait soudainement face à des rejets r8 maintenant. commutateur (error.getPrimaryError ()) {case SslError.SSL_UNTRUSTED: handler.proceed (); Pause; case SslError.SSL_EXPIRED: case SslError.SSL_IDMISMATCH: case SslError.SSL_NOTYETVALID: case SslError.SSL_DATE_INVALID: case SslError.SSL_INVALID: par défaut: handler.cancel (); Pause; }
Shivam Sharma
@JohnRubanSingh, aidez-moi s'il vous plaît. Nous pouvons rejoindre le jeu.
Shivam Sharma
0

La définition de ces deux propriétés a suffi à le faire fonctionner pour moi et ne présente pas de problèmes de sécurité:

 WebSettings settings = webView.getSettings();
    settings.setJavaScriptEnabled(true);
    settings.setDomStorageEnabled(true);
GreuM
la source
0

Utilisez cette ligne webview.getSettings (). SetDomStorageEnabled (true) dans votre code java

WebView webView = (WebView) findViewById(R.id.webview);    
webView.getSettings().setDomStorageEnabled(true);
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webView.loadUrl(yourUrl);
Abdul Basit Rishi
la source
0

Si vous souhaitez utiliser l'APK en dehors du Google Play Store, par exemple, une solution privée comme celle-ci fonctionnera probablement:

    @Override
    public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
        /*...*/
        handler.proceed();
    }

Si vous souhaitez ajouter une couche de sécurité facultative supplémentaire, vous pouvez essayer d'utiliser l' épinglage de certificat . IMHO ce n'est pas nécessaire pour un usage privé ou interne difficile.

Si vous prévoyez de publier l'application sur le Google Play Store, vous devez éviter @Override onReceivedSslError (...) {...}. Surtout en utilisant handler.proceed (). Google trouvera cet extrait de code et rejettera votre application à coup sûr puisque la solution avec handler.proceed () supprimera toutes sortes de mécanismes de sécurité intégrés .

Et ce n'est pas parce que les navigateurs ne se plaignent pas de votre connexion https que cela signifie que le certificat SSL lui-même est digne de confiance!

Dans mon cas, la chaîne de certificats SSL était rompue. Vous pouvez tester rapidement ces problèmes avec SSL Checker ou plus intermédiaire avec SSLLabs . Mais ne me demandez pas comment cela peut arriver. Je n'ai absolument aucune idée.

Quoi qu'il en soit, après la réinstallation du certificat SSL, toutes les erreurs concernant le " certificat SSL non approuvé dans WebView que ce soit " ont finalement disparu. J'ai également supprimé le @Override pour onReceivedSslError (...) et me suis débarrassé de handler.proceed () , et voila mon application n'a pas été rejetée par Google Play Store (encore une fois).

Manuel
la source