1

WebView is working fine with http requests and also https where well known Trusted sites like https://www.online.citibank.co.in/ But I try to access private site with CA issued from 3rd party, it is giving blank screen. Certificate is installed to the phone via SD card and listed under trusted certs list.

When i tried the same URL using HttpsURLConnection after adding the cert to TrustManager, it is working fine (able to get the content).

Following are the code snippet for WebView and HttpsURLConnection.

HttpsURLConnection: this below code works fine and able to get the content from the URL (I am not able to share the URL as it is not accessible from outside world)

try
{
    SSLContext context = null;

    CertificateFactory cf = CertificateFactory.getInstance("X.509");
    InputStream caInput = getResources().openRawResource(R.raw.mi_net);
    Certificate ca;
    try {
        ca = cf.generateCertificate(caInput);
    } finally {
        caInput.close();
    }

    // Create a KeyStore containing our trusted CAs
    String keyStoreType = KeyStore.getDefaultType();
    KeyStore keyStore = KeyStore.getInstance(keyStoreType);
    keyStore.load(null, null);
    keyStore.setCertificateEntry("ca", ca);

    // Create a TrustManager that trusts the CAs in our KeyStore
    String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
    TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
    tmf.init(keyStore);

    // Create an SSLContext that uses our TrustManager
    context = SSLContext.getInstance("TLS");
    context.init(null, tmf.getTrustManagers(), null);

    url = new URL(urlStr);
    HttpsURLConnection con = (HttpsURLConnection) url.openConnection();  
    con.setSSLSocketFactory(context.getSocketFactory());
    con.setInstanceFollowRedirects(true);

    con.setDoOutput(false);
    con.setConnectTimeout(1000);
    String responseMsg = con.getResponseMessage();
    response = con.getResponseCode();
    is = con.getInputStream();
}

WebView: Not working, called the callback onReceivedSslError

{
    WebSettings viewSettings = webView.getSettings();
    viewSettings.setJavaScriptEnabled(true);
    viewSettings.setAllowContentAccess(true);
    viewSettings.setBuiltInZoomControls(false);
    webView.getSettings().setRenderPriority(WebSettings.RenderPriority.HIGH);
    webView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
    webView.loadUrl(sameURL);

    webView.setWebViewClient(new WebViewClient() {
        @Override
        public void onPageStarted(final WebView view, final String url, Bitmap favicon) {
            Log.d("ann", "onPageStarted");

        }

        @Override
        public void onPageFinished(final WebView view, String url) {
            Log.d("ann", "inside onPageFinished");
        }

        @Override
        public void onReceivedError(WebView view, int errorCode,
                                    String description, String failingUrl) {

            if (!failingUrl.startsWith("mailto:")) {
                webView.loadUrl("file:///android_asset/html/error.html");
            }

        }

        @Override
        public void onReceivedSslError(WebView view, SslErrorHandler handler,
                                       SslError error) {
            super.onReceivedSslError(view, handler, error);
            Log.d("ann","SSL error");

            handler.proceed();
        }

    });}
}

Please help me with suggestion. WebViewClient exception is I/X509Util﹕ Failed to validate the certificate chain, error: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

Balaji S
  • 35
  • 1
  • 4

2 Answers2

0

For the HttpsUrlConnection you are creating the certificate from a file and setting it at runtime.

The Webview must be using whatever is in the system already.

Here is a similar question with a workaround proposed:

Check in the onReceivedSslError() method of a WebViewClient if a certificate is signed from a specific self-signed CA

Juan
  • 5,525
  • 2
  • 15
  • 26
  • @Override public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { // super.onReceivedSslError(view, handler, error); Log.d("ann","SSL error"); handler.proceed(); } after commenting the super function things started working for me. – Balaji S Aug 24 '17 at 21:20
  • Just note that this workaround lets you bypass the checking of the certificate, you should handle the logic to do this checking agains the certificate you are including as a file. Otherwise it is like not using https. – Juan Aug 24 '17 at 21:24
0

You can add your custom certificates manually to your android app!

Documentation link

Fortunately, you can teach your application to trust custom CAs by configuring your application's Network Security Config, without needing to modify the code inside your application.

Blog post on how to set it up

Aleksandar
  • 3,558
  • 1
  • 39
  • 42