Android WebView no carga una 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    
}

Cuando intento cargar una URL en WebBView, solo muestra una pantalla en blanco. Si cargo Google.com o yahoo.com, funciona bien.

sumitir
fuente
1
está funcionando, lo comprobé ahora. verifique nuevamente si no funciona luego agregue esto con su código webView.getSettings (). setUseWideViewPort (true); webView.getSettings (). setLoadWithOverviewMode (verdadero);
ilango j

Respuestas:

156

Por favor visite este enlace:

Agregue este método primordial a su implementación de WebViewClient. Deberá compilarlo con Android SDK 2.2 (API nivel 8) o posterior. El método aparece en el SDK público a partir de 2.2 (API nivel 8) pero lo hemos probado en dispositivos que ejecutan 2.1, 1.6 y 1.5 y también funciona en esos dispositivos (por lo que obviamente el comportamiento ha estado ahí todo el tiempo).

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

Esto te ayudara.

Fargath
fuente
3
La última entrada en la discusión funcionó muy bien. Muchas gracias.
Bill Lahti
55
Advertencia de seguridad : tenga en cuenta que hacerlo anula por completo el propósito de tener SSL en primer lugar.
ereOn
8
Por favor, no hagas esto. Es inseguro y no está permitido en Play Store.
Antimony
34
Google ahora está enviando correos electrónicos a quien implemente la solución anterior: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
Alguien sabe cómo resolver la advertencia de seguridad de Google, en caso afirmativo, hágamelo saber porque también estoy enfrentando este problema.
Pratik Tank
49

Por respuesta correcta por fargth, a continuación se muestra una pequeña muestra de código que podría ayudar.

Primero, cree una clase que amplíe WebViewClient y que esté configurada para ignorar los errores 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
            }

}

Luego, con su objeto de vista web (iniciado en el método OnCreate ()), configure su cliente de vista web para que sea una instancia de la clase de anulación:

 mWebView.setWebViewClient(
                new SSLTolerentWebViewClient()
        );
robnick
fuente
2
esto da la advertencia de seguridad de Google: implementación insegura del controlador WebViewClient.onReceivedSslError. ¿Sabes cómo resolver esto?
Pratik Tank
2
Google marcó la aplicación como Unsaif en Play Store, ¿cómo se puede hacer sin SSL?
Ajay Pandya
No utilice el método Super: super.onReceivedSslError (vista, controlador, error);
Atul Bhardwaj
41

Para manejar correctamente la validación del certificado SSL y evitar el rechazo de aplicaciones de Google de acuerdo con la nueva Política de seguridad, cambie su código para invocar SslErrorHandler.proceed () siempre que el certificado presentado por el servidor cumpla con sus expectativas, e invoque SslErrorHandler.cancel () de lo contrario.

Por ejemplo, agrego un cuadro de diálogo de alerta para que el usuario haya confirmado y parece que Google ya no muestra una advertencia.

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

Después de estos cambios, no mostrará ninguna advertencia.

Anant Shah
fuente
¿Qué pasará si elimino el bloque onReceivedSslError de la implementación?
Vivek Sinha
1
@VivekSinha llamará a handler.cancel (); por defecto.
Anant Shah
1
pero Google aún rechazó mi aplicación por el mismo motivo. ¿Por qué?
Vivek Sinha
@VivekSinha encontró alguna solución con respecto al lanzamiento de la aplicación en Play Store?
Kesha
2
Implementé la devolución de llamada onReceivedSslError como se sugirió. La aplicación se publicó con éxito posteriormente.
Vivek Sinha
11

Elimine el siguiente código, funcionará

 super.onReceivedSslError(view, handler, error);
Rey de misas
fuente
Genial, funcionó para mí. ¿Puede explicar cómo funcionó?
Arth Tilva
3
@ArthTilva de los documentos de Google: "el comportamiento predeterminado es cancelar la carga". Al llamar a super, está llamando a ese comportamiento predeterminado antes de que pueda llegar al resto del método. developer.android.com/reference/android/webkit/…
Josh Laird
11

anular onReceivedSslError y eliminar

super.onReceivedSslError (vista, controlador, error)

Y para solucionar la seguridad de Google:

setDomStorageEnabled (verdadero);

El código completo es:

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
fuente
Muchisimas gracias hombre. Eliminar super.onReceivedSslError (vista, controlador, error) funcionó para mí.
Däñish Shärmà
7

Copie y pegue su línea de código hermano, funcionará, confíe en mí :) Estoy pensando, obtiene un error ssl. Si usa override onReceivedSslError método y elimina super es super método. Simplemente escriba handler.proceed (), el error se resolverá.

    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
fuente
Gracias. Llame a handler.proceed () en onReceivedSslErrorsave my day
Tam Huynh
2
Si hace esto (ahora en julio de 2019), Google Play rechazará su solicitud.
Alp Altunel
Tengo demasiadas aplicaciones en Google Play, ninguna aplicación sigue siendo rechazada.
ozanurkan
1
rechazará enero de 2020 en palabras
John Ruban Singh
6

Para manejar URLs SSL, el método onReceivedSslError () de la clase WebViewClient, este es un ejemplo:

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

        });

Puede consultar mi ejemplo completo aquí: https://github.com/Jorgesys/Android-WebView-Logging

ingrese la descripción de la imagen aquí

Jorgesys
fuente
6

Para resolver la seguridad de Google, haga esto:

Líneas al principio:

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
fuente
2
Soy nuevo en Android. ¿Dónde debo poner esto? :)
Gediminas
5

Seguí las respuestas anteriores, pero aún parece que no me funciona a continuación, el código me hizo un truco al integrar las vías de pago, que generalmente son solicitudes 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();
        }
    }
}

El código anterior está haciendo una solicitud de publicación en la vista web y redirigiendo a la pasarela de pago.

La configuración me settings.setDomStorageEnabled(true);hizo un truco Espero que esto ayude.

KOTIOS
fuente
2
Esta solución deshabilita COMPLETAMENTE la validación de certificados, dejándolo abierto a ataques man-in-the-middle. Esto es algo que nunca debe hacer, ESPECIALMENTE para las pasarelas de pago.
Dirbaio
Para mí, inicialmente, la vista web no cargaba el contenido, sino solo la imagen de fondo de la página. Después de que lo agregué webview.getSettings.setDomStorageEnabled(true);mágicamente funcionó. Tal vez la página web esté usando algún tipo de API HTML 5, por lo que habilitar DomStorage funcionó para mí.
Ishant Sagar
handler.proceed () sin pasar por SSL
John Ruban Singh
qué es Encodingutil.getbyte
Akash kumar
2

El enfoque recomendado será

1. No llame al súper método (elimine la súper llamada del método anulado)

2.Google recomienda llamar al método SslErrorHandler.cancel () si surge algún error

3. Cuadro de diálogo No preguntar para exponer errores de SSL

¿Cuál es la mejor solución? Eliminar este método de anulación

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

}
John Ruban Singh
fuente
¿Estás pidiendo una solución o sugiriendo una?
Dharman
Sugiero este enfoque
John Ruban Singh
@JohnRubanSingh Hola John, he cargado un archivo JS desde los activos y una vez que el archivo se cargó con onPageFinished, llamo a una función dentro de JS. Entonces, anular onReceivedSslError () es necesario ya que estoy usando webview.setWebViewClient (nuevo ....)?
Shivam Sharma
Este código rechaza mi APK. Incluso desde hace 9 meses este código no causa rechazo sino que de repente enfrenta rechazos r8 ahora. switch (error.getPrimaryError ()) {case SslError.SSL_UNTRUSTED: handler.proceed (); romper; case SslError.SSL_EXPIRED: case SslError.SSL_IDMISMATCH: case SslError.SSL_NOTYETVALID: case SslError.SSL_DATE_INVALID: case SslError.SSL_INVALID: predeterminado: handler.cancel (); romper; }
Shivam Sharma
@JohnRubanSingh por favor ayúdame. Podemos unirnos con holgura.
Shivam Sharma
0

Establecer estas dos propiedades fue suficiente para que me funcionara y no me expone a problemas de seguridad:

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

Utilice esta línea webview.getSettings (). SetDomStorageEnabled (true) en su 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
fuente
0

En caso de que desee utilizar el APK fuera de Google Play Store, por ejemplo, una solución privada como la siguiente probablemente funcionará:

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

En caso de que desee agregar una capa de seguridad opcional adicional, puede intentar hacer uso de la fijación de certificados . En mi humilde opinión, esto no es necesario para uso privado o interno.

Si planeas publicar la aplicación en Google Play Store, debes evitar @Override onReceivedSslError (...) {...}. Especialmente haciendo uso de handler.proceed (). Google encontrará este fragmento de código y rechazará su aplicación con seguridad, ya que la solución con handler.proceed () suprimirá todo tipo de mecanismos de seguridad integrados .

Y solo por el hecho de que los navegadores no se quejan de su conexión https, no significa que el certificado SSL en sí sea de confianza.

En mi caso, la cadena de certificados SSL se rompió. Puede probar rápidamente estos problemas con SSL Checker o más intermedio con SSLLabs . Pero, por favor, no me pregunten cómo puede suceder esto. No tengo la menor idea.

De todos modos, después de reinstalar el certificado SSL, todos los errores relacionados con el " certificado SSL que no es de confianza en WebView " desaparecieron finalmente. También eliminé @Override para onReceivedSslError (...) y me deshice de handler.proceed () , y voila, mi aplicación no fue rechazada por Google Play Store (nuevamente).

Manuel
fuente