android中webView的https证书校验以及基于okhttp的接口https证书校验

webView证书校验:

通过chrome浏览器拿到证书cer文件

获取证书公钥

    public void readX509CerFile() {
        try {
            InputStream inStream = getAssets().open("ccc.cer");
            // 创建X509工厂类
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            // 创建证书对象
            X509Certificate oCert = (X509Certificate) cf
                    .generateCertificate(inStream);
            inStream.close();
            String info = null;
            // 获得证书版本
            Log.d(TAG, "publicKey: " + oCert.getPublicKey());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

证书公钥类

public class SslCert {

    public static final String[] keys = new String[]{
            "30820122300d06092a864886f70d01010105000382010f003082010a0282010100证书公钥0203010001"
    };
}

判断证书接口类

public class SslInterfance {


    public interface SslInterfase {
        void signSslResult(boolean result);
    }

    private static SslInterfase mSslInterfase;


    public static void setSslInterfase(SslInterfase sslInterfase) {
        mSslInterfase = sslInterfase;
    }


    public static void getUnsafeFromService(String url) {
        String[] publicKeys = SslCert.keys;
        try {
            X509TrustManager[] trustManagers = new X509TrustManager[]{
                    new X509TrustManager() {
                        @Override
                        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {

                        }

                        @Override
                        public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
                            if (x509Certificates == null) {
                                throw new IllegalArgumentException("check Service x509Certificates is null");
                            }
                            boolean expected = false;
                            for (X509Certificate certificate : x509Certificates) {
                                RSAPublicKey pubkey = (RSAPublicKey) certificate.getPublicKey();
                                String server = new BigInteger(1 /* positive */, pubkey.getEncoded()).toString(16);

                                for (String item : publicKeys) {//循环比对公钥,如果在信任列表里就验证成功
                                    if (item.equalsIgnoreCase(server)) {
                                        expected = true;
                                        break;
                                    }
                                }

                            }
                            Log.d("AAAAAAAAAQ", "expected: " + expected);
                            mSslInterfase.signSslResult(expected);
                        }

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

            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, trustManagers, null);
            final HostnameVerifier hostnameVerifier = new HostnameVerifier() {
                @Override
                public boolean verify(String hostname, SSLSession session) {
                    HostnameVerifier hostnameVerifier1 = HttpsURLConnection.getDefaultHostnameVerifier();
                    boolean result = hostnameVerifier1.verify("*", session);
                    return result;
                }
            };

            OkHttpClient okHttpClient = new OkHttpClient.Builder().hostnameVerifier(hostnameVerifier).sslSocketFactory(sslContext.getSocketFactory(), trustManagers[0]).build();
//            String url = "https://www.baidu.com";
            Request request = new Request.Builder().url(url).build();
            Call call = okHttpClient.newCall(request);
            call.enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
//                    Log.d("AAAAAAAAAQ", "onFailure: " + e.getMessage());
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    final String res = response.body().string();
//                    Log.d("AAAAAAAAAQ", "onResponse: " + res);
                }
            });

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

加载webView界面

SslInterfance.setSslInterfase(this);
SslInterfance.getUnsafeFromService(url);

回调方法

    @Override
    public void signSslResult(boolean result) {

        Log.d("AAAAAAAS", "signSslResult: " + result);
        if (result) {
            loadUrl(url);
        } else {
            loadUrl("file:///android_asset/Demo/blank.html");
            new Thread() {
                @Override
                public void run() {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(MAMCordovaActivity.this, "当前界面证书验证失败!", Toast.LENGTH_SHORT).show();
                        }
                    });
                }
            }.start();


        }

    }

接口证书校验:

判断证书公钥方法

    class PubKeyManager implements X509TrustManager {
        String[] publicKeys = SslCert.keys;

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

        }

        @Override
        //锁定证书公钥在apk中
        public void checkServerTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
            if (chain == null) {
                throw new IllegalArgumentException(
                        "checkServerTrusted: X509Certificate array is null");
            }
            if (!(chain.length > 0)) {
                throw new IllegalArgumentException(
                        "checkServerTrusted: X509Certificate is empty");
            }
            if (!((null != authType)
                    && (authType.equalsIgnoreCase("RSA"))
                    || authType.equalsIgnoreCase("ECDHE_RSA"))) {
                throw new CertificateException(
                        "checkServerTrusted: AuthType is not RSA");
            }
            // Perform customary SSL/TLS checks
            try {
                TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
                tmf.init((KeyStore) null);

                for (TrustManager trustManager : tmf.getTrustManagers()) {
                    ((X509TrustManager) trustManager).checkServerTrusted(chain,
                            authType);
                }
            } catch (Exception e) {
                throw new CertificateException(e);
            }

            // Hack ahead: BigInteger and toString(). We know a DER encoded Public Key begins
            // with 0?30 (ASN.1 SEQUENCE and CONSTRUCTED), so there is no leading 0?00 to drop.
            RSAPublicKey pubkey = (RSAPublicKey) chain[0].getPublicKey();
            String server = new BigInteger(1 /* positive */, pubkey.getEncoded()).toString(16);
            // Pin it!
            boolean expected = false;
            for (String item : publicKeys) {//循环比对公钥,如果在信任列表里就验证成功
                if (item.equalsIgnoreCase(server)) {
                    expected = true;
                    break;
                }
            }


            if (!expected) {
                throw new CertificateException(
                        "checkServerTrusted: Expected public key: " + server +
                                "not in trust");
            }
        }

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

创建OkHttpClient

private OkHttpClient okHttpClient = null;

OkHttpClient.Builder b = new OkHttpClient.Builder();
b.cookieJar(new CookieJar() {
    private final HashMap<String, List<Cookie>> cookieStore = new HashMap<>();

    @Override
    public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
        cookieStore.put(url.host(), cookies);
    }

    @Override
    public List<Cookie> loadForRequest(HttpUrl url) {
        List<Cookie> cookies = cookieStore.get(url.host());
        return cookies != null ? cookies : new ArrayList<Cookie>();
    }
}).connectTimeout(connectTimeout, TimeUnit.SECONDS)
        .writeTimeout(writeTimeout, TimeUnit.SECONDS)
        .readTimeout(readTimeout, TimeUnit.SECONDS);

以上代码通过this.okHttpClient = b.build();可以直接拿到okHttpClient。需要验证https证书需要对OkHttpClient.Builder继续进行操作

        OkHttpClient.Builder b = new OkHttpClient.Builder();
        b.cookieJar(new CookieJar() {
            private final HashMap<String, List<Cookie>> cookieStore = new HashMap<>();

            @Override
            public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
                cookieStore.put(url.host(), cookies);
            }

            @Override
            public List<Cookie> loadForRequest(HttpUrl url) {
                List<Cookie> cookies = cookieStore.get(url.host());
                return cookies != null ? cookies : new ArrayList<Cookie>();
            }
        }).connectTimeout(connectTimeout, TimeUnit.SECONDS)
                .writeTimeout(writeTimeout, TimeUnit.SECONDS)
                .readTimeout(readTimeout, TimeUnit.SECONDS);

        this.okHttpClientForUpdate = b.build();
        if (&& URL.startsWith("https")//https
                && (URL.contains(".baidu.com") || URL.contains(".aaaa.com"))//此处可以增加开关人为控制或根据域名控制
        ) {//cdn
            try {
                X509TrustManager trustManager;
                trustManager = new PubKeyManager();
                SSLSocketFactory sslSocketFactory = null;
                SSLContext sslContext = null;
                sslContext = SSLContext.getInstance("TLS");
                //使用构建出的trustManger初始化SSLContext对象
                sslContext.init(null, new TrustManager[]{trustManager}, null);
                //获得sslSocketFactory对象
                sslSocketFactory = sslContext.getSocketFactory();
                b.sslSocketFactory(sslSocketFactory, trustManager);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            b.hostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String hostname, SSLSession session) {
                    boolean verify = HttpsURLConnection.getDefaultHostnameVerifier().verify("*.baidu.com", session)
                            || HttpsURLConnection.getDefaultHostnameVerifier().verify("*.baiducdn.com", session);
                    return verify;
                }
            });
        }


        this.okHttpClient = b.build();

参考文章:Android安全开发之安全使用HTTPS - 阿里安全 - 博客园

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android提供了WebView控件来加载和显示Web页面。在使用WebView加载HTTPS网页时,SSL(即Secure Sockets Layer)是必需的。 SSL是一种用于在Internet上保护数据传输安全的加密协议。它确保在浏览器和服务器之间传输的数据是加密的,以防止第三方篡改或窃听数据。 要在Android WebView使用SSL,需要采取以下步骤: 1. 配置WebView设置:在代码,我们可以通过设置WebView的WebSettings对象来启用JavaScript和SSL,以便加载HTTPS网页。可以使用以下代码进行设置: ``` WebView webView = findViewById(R.id.webview); WebSettings webSettings = webView.getSettings(); webSettings.setJavaScriptEnabled(true); webSettings.setDomStorageEnabled(true); webSettings.setAppCacheEnabled(true); webSettings.setCacheMode(WebSettings.LOAD_DEFAULT); ``` 2. 导入SSL证书:有时候,我们需要导入服务器的SSL证书,以便WebView可以信任该服务器。可以使用以下代码导入SSL证书: ``` InputStream inputStream = getAssets().open("ssl_cert.cer"); CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); X509Certificate x509Certificate = (X509Certificate) certificateFactory.generateCertificate(inputStream); inputStream.close(); KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); keyStore.load(null, null); keyStore.setCertificateEntry("ssl_cert", x509Certificate); String defaultAlgorithm = KeyManagerFactory.getDefaultAlgorithm(); KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(defaultAlgorithm); keyManagerFactory.init(keyStore, null); TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(defaultAlgorithm); trustManagerFactory.init(keyStore); SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, trustManagerFactory.getTrustManagers(), null); SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); webSettings.setJavaScriptCanOpenWindowsAutomatically(true); webSettings.setUseWideViewPort(true); webSettings.setBuiltInZoomControls(true); webSettings.setDisplayZoomControls(false); webSettings.setSupportZoom(true); webSettings.setAllowFileAccess(true); webSettings.setAllowContentAccess(true); webView.setWebViewClient(new WebViewClient()); webView.getSettings().setJavaScriptEnabled(true); webView.loadUrl("https://www.example.com"); ``` 通过以上步骤,我们就可以在Android WebView加载HTTPS安全网页并保持通信的安全性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值