美文网首页
Okhttp 访问多个自签名证书 HTTPS 地址解决方案

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

作者: 真胖大海 | 来源:发表于2020-01-02 15:32 被阅读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();
    
    

    相关文章

      网友评论

          本文标题:Okhttp 访问多个自签名证书 HTTPS 地址解决方案

          本文链接:https://www.haomeiwen.com/subject/dxrooctx.html