我如何修复ssl异常错误并在android webview中加载https

时间:2017-05-10 04:44:21

标签: android ssl android-webview ssl-certificate

我正在尝试在webview中加载https,但它会给我ssl证书错误。我的网站已经有ssl证书,所以我不明白为什么它不允许加载安全网址。我按照一些代码提供下面的代码但我的客户要求他不希望在网站加载之前出现对话框。所以如何使用ssl证书加载我的网站。任何的想法?我不想使用beloew解决方案。

       @Override
        public void onReceivedSslError(WebView view, final SslErrorHandler handler, SslError error) {
//            final AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
//            builder.setMessage(R.string.notification_error_ssl_cert_invalid);
//            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();
//                    finish();
//                }
//            });
//            final AlertDialog dialog = builder.create();
//            dialog.show();





            String msg="";
            if(error.getPrimaryError()==SslError.SSL_DATE_INVALID
                    || error.getPrimaryError()== SslError.SSL_EXPIRED
                    || error.getPrimaryError()== SslError.SSL_IDMISMATCH
                    || error.getPrimaryError()== SslError.SSL_INVALID
                    || error.getPrimaryError()== SslError.SSL_NOTYETVALID
                    || error.getPrimaryError()==SslError.SSL_UNTRUSTED) {
                if(error.getPrimaryError()==SslError.SSL_DATE_INVALID){
                    msg="The date of the certificate is invalid";
                }else if(error.getPrimaryError()==SslError.SSL_INVALID){
                    msg="A generic error occurred";
                }
                else if(error.getPrimaryError()== SslError.SSL_EXPIRED){
                    msg="The certificate has expired";
                }else if(error.getPrimaryError()== SslError.SSL_IDMISMATCH){
                    msg="Hostname mismatch";
                }
                else if(error.getPrimaryError()== SslError.SSL_NOTYETVALID){
                    msg="The certificate is not yet valid";
                }
                else if(error.getPrimaryError()==SslError.SSL_UNTRUSTED){
                    msg="The certificate authority is not trusted";
                }
            }
            final AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
            builder.setMessage(msg);
            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();




        }

2 个答案:

答案 0 :(得分:0)

因为,当您从移动设备(客户端)向服务器发出请求时,服务器会将一些加密数据发送到您的移动设备(客户端)。因此需要通过该证书文件解密数据。所以你需要在你的手机中安装适当的.cer(或).crt文件。之后,您的问题可能会得到解决。

<强>更新

我添加了代码。在这里,您只需将您的SSL证书作为输入流格式在setCustomCertificateAuthority()方法中传递。

public class SslCertificateAuthority {

private static class UnifiedTrustManager implements X509TrustManager {
    private X509TrustManager defaultTrustManager;
    private X509TrustManager localTrustManager;
    public UnifiedTrustManager(KeyStore localKeyStore) throws KeyStoreException {
        try {
            this.defaultTrustManager = createTrustManager(null);
            this.localTrustManager = createTrustManager(localKeyStore);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }
    private X509TrustManager createTrustManager(KeyStore store) throws NoSuchAlgorithmException, KeyStoreException {
        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init((KeyStore) store);
        TrustManager[] trustManagers = tmf.getTrustManagers();
        return (X509TrustManager) trustManagers[0];
    }
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        try {
            defaultTrustManager.checkServerTrusted(chain, authType);
        } catch (CertificateException ce) {
            localTrustManager.checkServerTrusted(chain, authType);
        }
    }
    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        try {
            defaultTrustManager.checkClientTrusted(chain, authType);
        } catch (CertificateException ce) {
            localTrustManager.checkClientTrusted(chain, authType);
        }
    }
    @Override
    public X509Certificate[] getAcceptedIssuers() {
        X509Certificate[] first = defaultTrustManager.getAcceptedIssuers();
        X509Certificate[] second = localTrustManager.getAcceptedIssuers();
        X509Certificate[] result = Arrays.copyOf(first, first.length + second.length);
        System.arraycopy(second, 0, result, first.length, second.length);
        return result;
    }
}

public static void setCustomCertificateAuthority(InputStream inputStream) throws IOException {

    try {
        // Load CAs from an InputStream
        // (could be from a resource or ByteArrayInputStream or ...)
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        InputStream caInput = new BufferedInputStream(inputStream);
        Certificate ca;
        try {
            ca = cf.generateCertificate(caInput);
            System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
        } 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 and system CA
        UnifiedTrustManager trustManager = new UnifiedTrustManager(keyStore);

        // Create an SSLContext that uses our TrustManager
        SSLContext context = SSLContext.getInstance("TLS");
        context.init(null, new TrustManager[]{trustManager}, null);

        // Tell the URLConnection to use a SocketFactory from our SSLContext
        HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());

    } catch (CertificateException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (KeyStoreException e) {
        e.printStackTrace();
    } catch (KeyManagementException e) {
        e.printStackTrace();
    } catch (MalformedURLException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

}

答案 1 :(得分:0)

如果您需要HTTPS连接证书,可以将.bks文件作为原始资源添加到您的应用程序并扩展DefaultHttpConnection,以便您的证书用于HTTPS连接。

public class MyHttpClient extends DefaultHttpClient {

    private Resources resources;

    public MyHttpClient(Resources resources) {
        this.resources = resources;
    }

    @Override
    protected ClientConnectionManager createClientConnectionManager() {
        SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("http", PlainSocketFactory
            .getSocketFactory(), 80));
        if (resources != null) {
            registry.register(new Scheme("https", newSslSocketFactory(), 443));
        } else {
            registry.register(new Scheme("https", SSLSocketFactory
                .getSocketFactory(), 443));
        }
        return new SingleClientConnManager(getParams(), registry);
    }

    private SSLSocketFactory newSslSocketFactory() {
        try {
            KeyStore trusted = KeyStore.getInstance("BKS");
            InputStream in = resources.openRawResource(R.raw.mystore);
            try {
                trusted.load(in, "pwd".toCharArray());
            } finally {
                in.close();
            }
            return new SSLSocketFactory(trusted);
        } catch (Exception e) {
            throw new AssertionError(e);
        }
    }
}

这可以解决您的HTTPS ssl证书错误。

替代解决方案

使用以下代码

webView.setWebViewClient(new SSLTolerentWebViewClient());
webView.loadUrl(myhttps url);

和SSLTolerentWebViewClient类

private class SSLTolerentWebViewClient extends WebViewClient {
    public void onReceivedSslError(WebView view, final SslErrorHandler handler, SslError error) {

        AlertDialog.Builder builder = new AlertDialog.Builder(Tab1Activity.this);
        AlertDialog alertDialog = builder.create();
        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?";
        alertDialog.setTitle("SSL Certificate Error");
        alertDialog.setMessage(message);
        alertDialog.setButton(DialogInterface.BUTTON_POSITIVE, "OK", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                // Ignore SSL certificate errors
                handler.proceed();
            }
        });

        alertDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {

                handler.cancel();
            }
        });
        alertDialog.show();
    }
}