Android的webView加载双向认证的https网址

WebView加载自签名认证的https网址

加载https网址安全性提高很多,但是官方认证签名是需要钱的。所以自签名认证就出来了,WebView要添加证书认证后也是能显示的

双向认证签名

必须证书:cer,p12
存放路径:main下面的assets文件夹下,没有的自己新建

1.重写WebViewClient

public class SslPinningWebViewClient extends WebViewClient {

//private LoadedListener listener;
private SSLContext sslContext;
private int url_type;

public SslPinningWebViewClient() throws IOException {
    //this.listener = listener;

    // 添加cer证书
    List certificates = new ArrayList<>();

    List certs_data = NetConfig.getCertificatesData();

    // 将字节数组转为数组输入流

    if (certs_data != null && !certs_data.isEmpty()) {

        for (byte[] bytes : certs_data) {

            certificates.add(new ByteArrayInputStream(bytes));

        }

    }

    prepareSslPinning(certificates);
}

@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
    LogUtils.i("url_type", url_type + "a");
    view.loadUrl(url);
    if (url_type == 2) {
        return false;
    }
    return true;
}

public SslPinningWebViewClient(int url_type) throws IOException {
    //this.listener = listener;
    this.url_type = url_type;
    // 添加cer证书
    List certificates = new ArrayList<>();

    List certs_data = NetConfig.getCertificatesData();

    // 将字节数组转为数组输入流

    if (certs_data != null && !certs_data.isEmpty()) {

        for (byte[] bytes : certs_data) {

            certificates.add(new ByteArrayInputStream(bytes));

        }

    }

    prepareSslPinning(certificates);
}

@Override
public WebResourceResponse shouldInterceptRequest(final WebView view, String url) {
    LogUtils.i("shouldInterceptRequest", "shouldInterceptRequest1");
    return processRequest(url);

}

private WebResourceResponse processRequest(String webUrl) {
    LogUtils.i("SSL_PINNING_WEBVIEWS", "GET: " + webUrl.toString());

    try {
        // Setup connection
        URL url = new URL(webUrl);
        HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();

        // Set SSL Socket Factory for this request
        urlConnection.setSSLSocketFactory(sslContext.getSocketFactory());
        //很重要,验证证书
        urlConnection.setHostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        });

        // Get content, contentType and encoding
        InputStream is = urlConnection.getInputStream();
        String contentType = urlConnection.getContentType();
        String encoding = urlConnection.getContentEncoding();

        // If got a contentType header
        if (contentType != null) {

            String mimeType = contentType;

            // Parse mime type from contenttype string
            if (contentType.contains(";")) {
                mimeType = contentType.split(";")[0].trim();
            }

            LogUtils.i("SSL_PINNING_WEBVIEWS", "Mime: " + mimeType);

            //listener.Loaded(webUrl.toString());

            // Return the response
            return new WebResourceResponse(mimeType, encoding, is);
        }

    } catch (Exception e) {
        e.printStackTrace();
        if (isCause(CertPathValidatorException.class, e)) {
            //listener.PinningPreventedLoading(webUrl);
        }
        LogUtils.i("SSL_PINNING_WEBVIEWS", e.getLocalizedMessage());
    }

    // Return empty response for this request
    return new WebResourceResponse(null, null, null);
}

private void prepareSslPinning(List certificates) throws IOException {

    try {


        KeyManagerFactory keyManagerFactory = KeyManagerFactory
                .getInstance("X509");

        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("X509");

        KeyStore keyStore = KeyStore.getInstance("PKCS12");

        KeyStore keyStore2 = KeyStore.getInstance(KeyStore.getDefaultType());
        //读取证书
        InputStream ksIn = getResources().getAssets().open("mykey.p12");

        //加载证书
        keyStore2.load(null);
        keyStore.load(ksIn, "yibanyiban".toCharArray());

        ksIn.close();
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        try {
            for (int i = 0, size = certificates.size(); i < size; ) {
                InputStream certificate = certificates.get(i);
                String certificateAlias = Integer.toString(i++);
                keyStore2.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate));
                if (certificate != null)
                    certificate.close();
            }

        } catch (IOException e) {

            e.printStackTrace();

        }
        sslContext = SSLContext.getInstance("TLS");

        keyManagerFactory.init(keyStore, "yibanyiban".toCharArray());
        trustManagerFactory.init(keyStore2);
        sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);


    } catch (Exception e) {

        e.printStackTrace();

    }
}


private static TrustManager[] prepareTrustManager(InputStream... certificates) {
    if (certificates == null || certificates.length <= 0) return null;
    try {

        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        keyStore.load(null);
        int index = 0;
        for (InputStream certificate : certificates) {
            String certificateAlias = Integer.toString(index++);
            keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate));
            try {
                if (certificate != null)
                    certificate.close();
            } catch (IOException e)

            {
            }
        }
        TrustManagerFactory trustManagerFactory = null;

        trustManagerFactory = TrustManagerFactory.
                getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(keyStore);

        TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();

        return trustManagers;
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (CertificateException e) {
        e.printStackTrace();
    } catch (KeyStoreException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;

}

private static KeyManager[] prepareKeyManager(InputStream bksFile, String password) {
    try {
        if (bksFile == null || password == null) return null;

        KeyStore clientKeyStore = KeyStore.getInstance("PKCS12");
        clientKeyStore.load(bksFile, password.toCharArray());
        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(clientKeyStore, password.toCharArray());
        return keyManagerFactory.getKeyManagers();

    } catch (KeyStoreException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (UnrecoverableKeyException e) {
        e.printStackTrace();
    } catch (CertificateException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

private static X509TrustManager chooseTrustManager(TrustManager[] trustManagers) {
    for (TrustManager trustManager : trustManagers) {
        if (trustManager instanceof X509TrustManager) {
            return (X509TrustManager) trustManager;
        }
    }
    return null;
}


private static class MyTrustManager implements X509TrustManager {
    private X509TrustManager defaultTrustManager;
    private X509TrustManager localTrustManager;

    public MyTrustManager(X509TrustManager localTrustManager) throws NoSuchAlgorithmException, KeyStoreException {
        TrustManagerFactory var4 = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        var4.init((KeyStore) null);
        defaultTrustManager = chooseTrustManager(var4.getTrustManagers());
        this.localTrustManager = localTrustManager;
    }


    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {

    }

    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        try {
            defaultTrustManager.checkServerTrusted(chain, authType);
        } catch (CertificateException ce) {
            localTrustManager.checkServerTrusted(chain, authType);
        }
    }


    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return new X509Certificate[0];
    }
}

public static boolean isCause(
        Class expected,
        Throwable exc
) {
    return expected.isInstance(exc) || (
            exc != null && isCause(expected, exc.getCause())
    );
}

@Override
public void onPageFinished(WebView view, String url) {
    super.onPageFinished(view, url);
} }

注:上面很重要部分真的很重要

2.NetConfig读取cer证书

public class NetConfig {
// 证书数据
private static List CERTIFICATES_DATA = new ArrayList<>();
/**
 * 添加https证书
 * @param inputStream
 */
public synchronized static void addCertificate(InputStream inputStream) {

    if (inputStream != null) {
        try {
            int ava = 0;// 数据当次可读长度
            int len = 0;// 数据总长度
            ArrayList data = new ArrayList<>();
            while ((ava = inputStream.available()) > 0) {
                byte[] buffer = new byte[ava];
                inputStream.read(buffer);
                data.add(buffer);
                len += ava;
            }

            byte[] buff = new byte[len];
            int dstPos = 0;
            for (byte[] bytes:data) {
                int length = bytes.length;
                System.arraycopy(bytes, 0, buff, dstPos, length);
                dstPos += length;
            }
            CERTIFICATES_DATA.add(buff);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

/**
 * https证书
 * @return
 */
public static List getCertificatesData() {
    return CERTIFICATES_DATA;
}}

3.MyApplication读cer###

/**
 * 读取cer证书
 */
private void readCer() {
    // 添加https证书
    try {
        InputStream is = getAssets().open("tomcat.cer");
        NetConfig.addCertificate(is); // 这里将证书读取出来,,放在配置中byte[]里

    } catch (IOException ioe) {
        ioe.printStackTrace();
    }
}

写这个方法后,在OnCreate()中调用

4.webview的使用

SslPinningWebViewClient webViewClient = null;
            try {
                webViewClient = new SslPinningWebViewClient();
            } catch (IOException e) {
                e.printStackTrace();
            }
            //采用自定义WebViewClient
            wvMain.setWebViewClient(webViewClient);

在做之前可以先在电脑浏览器上试证书是否是能用的,至于方法百度。如果证书能用,基本通过上面步骤是没问题的。
这篇文章在csdn上面也有。
但都是我的,哈哈
还有问题可私信我

你可能感兴趣的:(Android的webView加载双向认证的https网址)