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  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上面也有。
但都是我的,哈哈
还有问题可私信我

发表评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注