Okhttp 访问多个自签名证书 HTTPS 地址解决方案

2020-01-02  本文已影响0人  真胖大海

首先参考
Okhttp 访问自签名证书 HTTPS 地址解决方案
上面这篇博客,解决了访问自签名证书的问题。
但是有时候我们要访问过多域名,每个域名的证书又不一样我们应该怎样做呢


    private SSLSocketFactory createSSLSocketFactory() {
        SSLSocketFactory ssfFactory = null;
        try {
            MyTrustManager mMyTrustManager = new MyTrustManager();
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, new TrustManager[]{mMyTrustManager}, new SecureRandom());
            ssfFactory = sc.getSocketFactory();
        } catch (Exception ignored) {
            ignored.printStackTrace();
        }

        return ssfFactory;
    }

    //实现X509TrustManager接口
    public class MyTrustManager implements X509TrustManager {
        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        }

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

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

    //实现HostnameVerifier接口
    private class TrustAllHostnameVerifier implements HostnameVerifier {
        @Override
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    }

    /**
     * 获去信任自签证书的trustManager
     *
     * @param ins 自签证书输入流
     * @return 信任自签证书的trustManager
     * @throws GeneralSecurityException
     */
    private X509TrustManager trustManagerForCertificates(InputStream... ins)
            throws GeneralSecurityException {
        //创建证书工厂
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");

        //通过证书工厂得到自签证书对象集合
        Collection<Certificate> certificates = new ArrayList<>();

        for (InputStream inputStream : ins) {
            certificates.addAll(certificateFactory.generateCertificates(inputStream));
        }

        if (certificates.isEmpty()) {
            throw new IllegalArgumentException("expected non-empty set of trusted certificates");
        }

        //为证书设置一个keyStore
        char[] password = "password".toCharArray(); // Any password will work.
        KeyStore keyStore = newEmptyKeyStore(password);
        int index = 0;
        //将所有证书放入证书放入keystore中
        for (Certificate certificate : certificates) {
            String certificateAlias = Integer.toString(index++);
            keyStore.setCertificateEntry(certificateAlias, certificate);
        }


        // Use it to build an X509 trust manager.
        //使用包含自签证书信息的keyStore去构建一个X509TrustManager
        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(
                KeyManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(keyStore, password);
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
                TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(keyStore);
        TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
        if (trustManagers.length == 0) {
            throw new IllegalStateException("Unexpected default trust managers:"
                    + Arrays.toString(trustManagers));
        }
        return ((X509TrustManager) trustManagers[0]);
    }

    private KeyStore newEmptyKeyStore(char[] password) throws GeneralSecurityException {
        try {
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            InputStream in = null; // By convention, 'null' creates an empty key store.
            keyStore.load(null, password);
            return keyStore;
        } catch (IOException e) {
            throw new AssertionError(e);
        }
    }

trustManagerForCertificates.(InputStream...ins)为证书的输入流
比如证书文件有两个 1.crt2.crt

  X509TrustManager x509TrustManager = trustManagerForCertificates(
                new FileInputStream(new File("1.crt")), new FileInputStream(new File("2.crt"))
        );
//获取到SSLSocketFactory和X509TrustManager
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .sslSocketFactory(createSSLSocketFactory(),x509TrustManager )
                .build();

上一篇下一篇

猜你喜欢

热点阅读