Android WebView não carrega um 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    
}

Quando tento carregar uma URL no WebBView, ele só mostra uma tela em branco. Se eu carregar o Google.com ou o yahoo.com, está funcionando bem.

cume
fonte
1
está funcionando, verifiquei agora. verifique novamente se não estiver funcionando, depois adicione isso com seu código webView.getSettings (). setUseWideViewPort (true); webView.getSettings (). setLoadWithOverviewMode (true);
ilango j

Respostas:

154

Visite este link:

Adicione este método de substituição à sua implementação WebViewClient. Você precisará compilá-lo com Android SDK 2.2 (API nível 8) ou posterior. O método aparece no SDK público a partir de 2.2 (API nível 8), mas nós o testamos em dispositivos executando 2.1, 1.6 e 1.5 e ele funciona nesses dispositivos também (então, obviamente, o comportamento sempre existiu).

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

isso vai te ajudar.

Fargath
fonte
3
A última entrada na discussão funcionou muito bem. Muito obrigado.
Bill Lahti
54
Aviso de segurança : Observe que fazer isso anula completamente o propósito de ter SSL em primeiro lugar.
ereOn
8
Por favor, não faça isso. É inseguro e não é permitido na Play Store.
Antimônio
33
O Google agora está enviando e-mails para quem implantar a solução acima: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
Alguém sabe como resolver o aviso de Segurança do google, se sim avise-me pois também estou enfrentando esse problema.
Pratik Tank
48

Por resposta correta por fargth, segue um pequeno exemplo de código que pode ajudar.

Primeiro, crie uma classe que estenda WebViewClient e que seja configurada para ignorar erros de 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
            }

}

Em seguida, com seu objeto de visualização da web (iniciado no método OnCreate ()), defina seu cliente de visualização da web como uma instância da classe de substituição:

 mWebView.setWebViewClient(
                new SSLTolerentWebViewClient()
        );
robnick
fonte
2
isso fornece o aviso de segurança do Google: implementação insegura do manipulador WebViewClient.onReceivedSslError. você sabe como resolver isso?
Tanque Pratik
2
O Google marcou o aplicativo como não seguro na playstore, como posso fazer isso sem SSL?
Ajay Pandya
Não use o método Super- super.onReceivedSslError (view, handler, error);
Atul Bhardwaj
40

Para lidar adequadamente com a validação do certificado SSL e evitar a rejeição do aplicativo do Google de acordo com a nova Política de Segurança, altere seu código para invocar SslErrorHandler.proceed () sempre que o certificado apresentado pelo servidor atender às suas expectativas e invoque SslErrorHandler.cancel () caso contrário.

Por exemplo, adiciono uma caixa de diálogo de alerta para fazer com que o usuário tenha confirmado e pareça que o Google não mostra mais o aviso.

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

Após essas alterações não haverá aviso.

Anant Shah
fonte
o que acontecerá se eu remover o bloco onReceivedSslError da implementação?
Vivek Sinha
1
@VivekSinha irá chamar handler.cancel (); por padrão.
Anant Shah
1
mas o Google ainda rejeitou meu aplicativo dizendo o mesmo motivo. Por quê?
Vivek Sinha
A @VivekSinha encontrou alguma solução em relação ao lançamento do app na Play Store?
Kesha,
2
Implementei o retorno de chamada onReceivedSslError conforme sugerido. O aplicativo foi publicado com sucesso posteriormente.
Vivek Sinha
11

Remova o código abaixo que funcionará

 super.onReceivedSslError(view, handler, error);
Rei das missas
fonte
Ótimo, funcionou para mim. Você pode explicar como funcionou?
Arth Tilva
3
@ArthTilva do google docs: "comportamento padrão é cancelar o carregamento". Ao chamar super, você está chamando esse comportamento padrão antes que ele alcance o resto do método. developer.android.com/reference/android/webkit/…
Josh Laird
11

substituir onReceivedSslError e remover

super.onReceivedSslError (visualização, manipulador, erro)

E para solucionar a segurança do Google:

setDomStorageEnabled (true);

O código completo é:

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
fonte
Muito obrigado, cara. Remover super.onReceivedSslError (view, handler, error) funcionou para mim.
Däñish Shärmà
7

Copie e cole sua linha de código, mano, funcionará, confie em mim :) Estou pensando, você obteve um erro de SSL. Se você usar o método override onReceivedSslError e remover o método super, é super. Basta escrever handler.proceed (), o erro será resolvido.

    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
fonte
Obrigado. Chame handler.proceed () em onReceivedSslErrorsave my day
Tam Huynh
2
Se você fizer isso (agora em julho de 2019), o Google Play rejeitará sua inscrição.
Alp Altunel de
Tenho muitos aplicativos no Google Play, nenhum aplicativo ainda será rejeitado.
ozanurkan
1
rejeitará janeiro de 2020 on-words
John Ruban Singh
6

Para lidar com URLs SSL, o método onReceivedSslError () da classe WebViewClient. Este é um exemplo:

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

        });

Você pode verificar meu exemplo completo aqui: https://github.com/Jorgesys/Android-WebView-Logging

insira a descrição da imagem aqui

Jorgesys
fonte
6

Para solucionar a segurança do Google, faça o seguinte:

Linhas no topo:

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

Código:

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
fonte
2
Sou novo no Android. Onde devo colocar isso? :)
Gediminas
5

Eu segui as respostas acima, mas ainda parece não estar funcionando para mim o código abaixo fez um truque para mim ao integrar gatways de pagamento que geralmente são solicitações 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();
        }
    }
}

O código acima está fazendo uma solicitação de postagem em webview e redirecionando para o gateway de pagamento.

Definir settings.setDomStorageEnabled(true);fez um truque para mim Espero que isso ajude.

KOTIOS
fonte
2
Esta solução desabilita COMPLETAMENTE a validação de certificado, deixando você aberto para ataques man-in-the-middle. Isso é algo que você nunca deve fazer, ESPECIALMENTE para gateways de pagamento.
Dirbaio 01 de
Para mim, inicialmente o webview não carregava o conteúdo, mas apenas a imagem de fundo da página. Depois de adicionar webview.getSettings.setDomStorageEnabled(true);, funcionou magicamente. Talvez a página da web esteja usando algum tipo de API HTML 5, então habilitar o DomStorage funcionou para mim.
Ishant Sagar
handler.proceed () ignorando SSL
John Ruban Singh
o que é Encodingutil.getbyte
Akash kumar
2

A abordagem recomendada será

1. Não chame o super método (Remova a super chamada do método substituído)

2. O Google recomenda chamar o método SslErrorHandler.cancel () se ocorrer algum erro

3. Não solicitar a caixa de diálogo para expor erros de SSL

Qual é a melhor solução ?? Remova este método de substituição

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

}
John Ruban Singh
fonte
Você está pedindo uma solução ou sugerindo uma?
Dharman
Estou sugerindo esta abordagem
John Ruban Singh
@JohnRubanSingh Olá John, Estou carregando um arquivo JS de ativos e, uma vez que o arquivo é carregado com onPageFinished, estou chamando uma função dentro de JS. Portanto, substituir onReceivedSslError () é necessário, pois estou usando webview.setWebViewClient (new ....)?
Shivam Sharma
Este código rejeita meu APK.Mesmo há 9 meses, este código não causa rejeição, mas de repente enfrenta rejeições r8 agora. switch (error.getPrimaryError ()) {case SslError.SSL_UNTRUSTED: handler.proceed (); pausa; case SslError.SSL_EXPIRED: case SslError.SSL_IDMISMATCH: case SslError.SSL_NOTYETVALID: case SslError.SSL_DATE_INVALID: case SslError.SSL_INVALID: default: handler (handler); pausa; }
Shivam Sharma
@JohnRubanSingh por favor me ajude. Podemos entrar na folga.
Shivam Sharma
0

Definir essas duas propriedades foi suficiente para fazer funcionar para mim e não expõe a problemas de segurança:

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

Use esta linha webview.getSettings (). SetDomStorageEnabled (true) em seu código 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
fonte
0

Caso você queira usar o APK fora da Google Play Store, por exemplo, privado, uma solução como a seguinte provavelmente funcionará:

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

Caso queira adicionar uma camada opcional adicional de segurança, você pode tentar fazer uso da fixação de certificado . IMHO isso não é necessário para uso privado ou interno difícil.

Se você planeja publicar o aplicativo na Google Play Store, deve evitar @Override onReceivedSslError (...) {...}. Especialmente usando handler.proceed (). O Google encontrará esse snippet de código e rejeitará seu aplicativo com certeza, pois a solução com handler.proceed () suprimirá todos os tipos de mecanismos de segurança integrados .

E só porque os navegadores não reclamam da sua conexão https, isso não significa que o próprio certificado SSL seja confiável!

No meu caso, a cadeia de certificados SSL foi quebrada. Você pode testar rapidamente esses problemas com SSL Checker ou mais intermediário com SSLLabs . Mas, por favor, não me pergunte como isso pode acontecer. Eu não tenho absolutamente nenhuma ideia.

De qualquer forma, depois de reinstalar o certificado SSL, todos os erros referentes ao " certificado SSL não confiável em WebView qualquer " desapareceram finalmente. Eu também removi @Override para onReceivedSslError (...) e me livrei de handler.proceed () , e pronto, meu aplicativo não foi rejeitado pela Google Play Store (de novo).

Manuel
fonte