Android WebView nie ładuje adresu 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    
}

Kiedy próbuję załadować adres URL w WebBView, pokazuje tylko pusty ekran. Jeśli załaduję Google.com lub yahoo.com, wszystko działa dobrze.

sumit
źródło
1
działa, sprawdziłem teraz. sprawdź ponownie, jeśli nie działa, po czym dodaj to w swoim kodzie webView.getSettings (). setUseWideViewPort (true); webView.getSettings (). setLoadWithOverviewMode (true);
ilango j

Odpowiedzi:

155

Odwiedź ten link:

Dodaj tę zastępującą metodę do implementacji WebViewClient. Musisz go skompilować za pomocą zestawu Android SDK 2.2 (poziom interfejsu API 8) lub nowszego. Metoda pojawia się w publicznym SDK od wersji 2.2 (poziom API 8), ale przetestowaliśmy ją na urządzeniach z systemem 2.1, 1.6 i 1.5 i działa również na tych urządzeniach (więc oczywiście zachowanie było obecne przez cały czas).

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

to ci pomoże.

fargath
źródło
3
Ostatni wpis w dyskusji sprawdził się świetnie. Dziękuję bardzo.
Bill Lahti,
54
Ostrzeżenie dotyczące bezpieczeństwa : należy pamiętać, że takie działanie całkowicie mija się z celem posiadania SSL.
ereOn
8
Proszę, nie rób tego. To niebezpieczne i niedozwolone w Sklepie Play.
Antymon
33
Google wysyła teraz e-maile do każdego, kto wdraża powyższe rozwiązanie: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
Każdy wie, jak rozwiązać ostrzeżenie Google dotyczące bezpieczeństwa, jeśli tak, daj mi znać, ponieważ ja również mam do czynienia z tym problemem.
Pratik Tank
49

Zgodnie z poprawną odpowiedzią Fargth, poniżej znajduje się mały przykład kodu, który może pomóc.

Najpierw utwórz klasę rozszerzającą WebViewClient i ustawioną na ignorowanie błędów 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
            }

}

Następnie za pomocą obiektu widoku internetowego (zainicjowanego w metodzie OnCreate ()) ustaw jego klienta widoku internetowego jako instancję klasy override:

 mWebView.setWebViewClient(
                new SSLTolerentWebViewClient()
        );
robnick
źródło
2
powoduje to ostrzeżenie Google o bezpieczeństwie: niebezpieczna implementacja modułu obsługi WebViewClient.onReceivedSslError. czy wiesz, jak to rozwiązać?
Pratik Tank
2
Google oznaczył aplikację jako Unsaif w playstore, jak można to zrobić bez SSL?
Ajay Pandya
Nie używaj metody Super - super.onReceivedSslError (widok, obsługa, błąd);
Atul Bhardwaj
41

Aby prawidłowo obsługiwać weryfikację certyfikatu SSL i uniknąć odrzucania aplikacji przez Google zgodnie z nową polityką bezpieczeństwa, zmień kod tak, aby wywoływał SslErrorHandler.proceed () zawsze, gdy certyfikat przedstawiony przez serwer spełnia Twoje oczekiwania, a w przeciwnym razie wywołaj SslErrorHandler.cancel ().

Na przykład dodaję okno dialogowe z ostrzeżeniem, aby użytkownik potwierdził, i wydaje się, że Google nie wyświetla już ostrzeżenia.

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

Po tej zmianie nie wyświetli ostrzeżenia.

Anant Shah
źródło
co się stanie, jeśli usunę blok onReceivedSslError z implementacji?
Vivek Sinha,
1
@VivekSinha wywoła handler.cancel (); domyślnie.
Anant Shah,
1
ale Google nadal odrzuca moją aplikację, podając ten sam powód. Czemu?
Vivek Sinha
@VivekSinha znalazł jakieś rozwiązanie dotyczące uruchamiania aplikacji w Sklepie Play?
Kesha,
2
Zaimplementowałem wywołanie zwrotne onReceivedSslError zgodnie z sugestią. Aplikacja została później pomyślnie opublikowana.
Vivek Sinha,
11

Usuń poniższy kod, który zadziała

 super.onReceivedSslError(view, handler, error);
Król Mszy
źródło
Świetnie, u mnie zadziałało. Czy możesz wyjaśnić, jak to działało?
Arth Tilva
3
@ArthTilva z dokumentów google: „Domyślnym zachowaniem jest anulowanie ładowania”. Wywołując super, wywołujesz to domyślne zachowanie, zanim dotrze do reszty metody. developer.android.com/reference/android/webkit/…
Josh Laird
11

nadpisz onReceivedSslError i usuń

super.onReceivedSslError (widok, program obsługi, błąd)

Aby rozwiązać problem bezpieczeństwa Google:

setDomStorageEnabled (true);

Pełny kod to:

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
źródło
Dziękuję bardzo stary. Usunięcie super.onReceivedSslError (widok, program obsługi, błąd) zadziałało.
Däñish Shärmà
7

Skopiuj i wklej swój kod linii brachu, to zadziała, zaufaj mi :) Myślę, że pojawia się błąd ssl. Jeśli używasz zastąpienia metody onReceivedSslError i usuniesz super, jest to super metoda. Po prostu napisz handler.proceed (), błąd zostanie rozwiązany.

    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
źródło
Dzięki. Call handler.proceed () in onReceivedSslErrorsave my day
Tam Huynh
2
Jeśli to zrobisz (teraz lipiec 2019), Google Play odrzuci Twoje zgłoszenie.
Alp Altunel,
Mam zbyt wiele aplikacji w Google Play, żadna aplikacja nadal nie jest odrzucana.
ozanurkan
1
odrzuci słowa ze stycznia 2020 roku
John Ruban Singh
6

Do obsługi adresów URL SSL służy metoda onReceivedSslError () z klasy WebViewClient, oto przykład:

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

        });

Możesz sprawdzić mój pełny przykład tutaj: https://github.com/Jorgesys/Android-WebView-Logging

wprowadź opis obrazu tutaj

Jorgesys
źródło
6

Aby rozwiązać problemy z bezpieczeństwem Google, wykonaj następujące czynności:

Linie na górę:

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

Kod:

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
źródło
2
Jestem nowy w Androidzie. Gdzie mam to położyć? :)
Gediminas
5

Postępowałem zgodnie z powyższymi odpowiedziami, ale nadal wydaje mi się, że nie działa dla mnie.Poniższy kod zrobił dla mnie sztuczkę podczas integracji bram płatniczych, które zwykle są żądaniami 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();
        }
    }
}

Powyższy kod wykonuje żądanie wpisu w przeglądarce internetowej i przekierowuje do bramki płatności.

Ustawienie settings.setDomStorageEnabled(true);zrobiło dla mnie sztuczkę. Mam nadzieję, że to pomaga.

KOTIOS
źródło
2
To rozwiązanie CAŁKOWICIE wyłącza weryfikację certyfikatów, pozostawiając Cię otwartym na ataki typu man-in-the-middle. Jest to coś, czego nigdy nie powinieneś robić, SZCZEGÓLNIE w przypadku bramek płatniczych.
Dirbaio
Dla mnie początkowo przeglądarka nie ładowała treści, a jedynie obraz tła strony. Po dodaniu webview.getSettings.setDomStorageEnabled(true);to magicznie zadziałało. Może strona korzysta z jakiegoś interfejsu API HTML 5, więc włączenie DomStorage zadziałało.
Ishant Sagar
handler.proceed () omijając SSL
John Ruban Singh
co to jest Encodingutil.getbyte
Akash kumar
2

Zalecane podejście będzie

1. Nie wywołuj super metody (Usuń super wywołanie z metody zastępowanej)

2. Google zaleca wywołanie metody SslErrorHandler.cancel () w przypadku wystąpienia błędu

3. Nie pytaj, aby ujawnić błędy SSL

Jakie jest najlepsze rozwiązanie? Usuń tę metodę zastępowania

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

}
John Ruban Singh
źródło
Pytasz o rozwiązanie lub je sugerujesz?
Dharman
Sugeruję takie podejście
John Ruban Singh
@JohnRubanSingh Cześć John, ładuję plik JS z zasobów i po załadowaniu pliku za pomocą onPageFinished wywołuję funkcję wewnątrz JS. Zatem przesłanianie onReceivedSslError () jest konieczne, ponieważ używam webview.setWebViewClient (nowy ....)?
Shivam Sharma
Ten kod odrzuca mój plik APK. Nawet od 9 miesięcy ten kod nie powoduje odrzucenia, ale nagle stoi teraz w obliczu odrzucenia r8. switch (error.getPrimaryError ()) {case SslError.SSL_UNTRUSTED: handler.proceed (); złamać; case SslError.SSL_EXPIRED: case SslError.SSL_IDMISMATCH: case SslError.SSL_NOTYETVALID: case SslError.SSL_DATE_INVALID: case SslError.SSL_INVALID: default: handler.cancel (); złamać; }
Shivam Sharma
@JohnRubanSingh proszę mi pomóc. Możemy dołączyć na luzie.
Shivam Sharma
0

Ustawienie tych dwóch właściwości wystarczyło, aby działał dla mnie i nie naraża na problemy z bezpieczeństwem:

 WebSettings settings = webView.getSettings();
    settings.setJavaScriptEnabled(true);
    settings.setDomStorageEnabled(true);
GreuM
źródło
0

Użyj tej linii webview.getSettings (). SetDomStorageEnabled (true) w swoim kodzie 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
źródło
0

W przypadku, gdy chcesz korzystać z APK poza Sklepem Google Play, np. Prywatne rozwiązanie takie jak poniższe prawdopodobnie zadziała:

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

Jeśli chcesz dodać dodatkową opcjonalną warstwę zabezpieczeń, możesz spróbować skorzystać z przypinania certyfikatu . IMHO nie jest to konieczne do trudnego użytku prywatnego lub wewnętrznego.

Jeśli planujesz opublikować aplikację w sklepie Google Play, powinieneś unikać @Override onReceivedSslError (...) {...}. Szczególnie przy użyciu handler.proceed (). Google znajdzie ten fragment kodu i na pewno odrzuci Twoją aplikację, ponieważ rozwiązanie z funkcją handler.proceed () zablokuje wszelkiego rodzaju wbudowane mechanizmy bezpieczeństwa .

I tylko dlatego, że przeglądarki nie narzekają na twoje połączenie https, nie oznacza to, że sam certyfikat SSL jest w ogóle zaufany!

W moim przypadku łańcuch certyfikatów SSL został zerwany. Możesz szybko przetestować takie problemy za pomocą SSL Checker lub bardziej średniozaawansowanych z SSLLabs . Ale proszę, nie pytaj mnie, jak to się może stać. Nie mam pojęcia.

W każdym razie, po ponownej instalacji certyfikatu SSL, wszystkie błędy dotyczące „ niezaufanego certyfikatu SSL w ogóle w WebView ” w końcu zniknęły. Usunąłem również @Override dla onReceivedSslError (...) i pozbyłem się handler.proceed () , a é voila, moja aplikacja nie została odrzucona przez Sklep Google Play (ponownie).

Manuel
źródło