原文:https://blog.csdn.net/justry_deng/article/details/81042379
相关方法详情(非完美封装):
/** * 根据是否是https请求,获取HttpClient客户端 * * TODO 本人这里没有进行完美封装。对于 校不校验校验证书的选择,本人这里是写死 * 在代码里面的,你们在使用时,可以灵活二次封装。 * * 提示: 此工具类的封装、相关客户端、服务端证书的生成,可参考我的这篇博客: * <linked>https://blog.csdn.net/justry_deng/article/details/91569132</linked> * * * @param isHttps 是否是HTTPS请求 * * @return HttpClient实例 * @date 2019/9/18 17:57 */ private CloseableHttpClient getHttpClient(boolean isHttps) { CloseableHttpClient httpClient; if (isHttps) { SSLConnectionSocketFactory sslSocketFactory; try { /// 如果不作证书校验的话 sslSocketFactory = getSocketFactory(false, null, null); /// 如果需要证书检验的话 // 证书 //InputStream ca = this.getClass().getClassLoader().getResourceAsStream("client/ds.crt"); // 证书的别名,即:key。 注:cAalias只需要保证唯一即可,不过推荐使用生成keystore时使用的别名。 // String cAalias = System.currentTimeMillis() + "" + new SecureRandom().nextInt(1000); //sslSocketFactory = getSocketFactory(true, ca, cAalias); } catch (Exception e) { throw new RuntimeException(e); } httpClient = HttpClientBuilder.create().setSSLSocketFactory(sslSocketFactory).build(); return httpClient; } httpClient = HttpClientBuilder.create().build(); return httpClient; } /** * HTTPS辅助方法, 为HTTPS请求 创建SSLSocketFactory实例、TrustManager实例 * * @param needVerifyCa * 是否需要检验CA证书(即:是否需要检验服务器的身份) * @param caInputStream * CA证书。(若不需要检验证书,那么此处传null即可) * @param cAalias * 别名。(若不需要检验证书,那么此处传null即可) * 注意:别名应该是唯一的, 别名不要和其他的别名一样,否者会覆盖之前的相同别名的证书信息。别名即key-value中的key。 * * @return SSLConnectionSocketFactory实例 * @throws NoSuchAlgorithmException * 异常信息 * @throws CertificateException * 异常信息 * @throws KeyStoreException * 异常信息 * @throws IOException * 异常信息 * @throws KeyManagementException * 异常信息 * @date 2019/6/11 19:52 */ private static SSLConnectionSocketFactory getSocketFactory(boolean needVerifyCa, InputStream caInputStream, String cAalias) throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException, KeyManagementException { X509TrustManager x509TrustManager; // https请求,需要校验证书 if (needVerifyCa) { KeyStore keyStore = getKeyStore(caInputStream, cAalias); TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); trustManagerFactory.init(keyStore); TrustManager[] trustManagers = trustManagerFactory.getTrustManagers(); if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) { throw new IllegalStateException("Unexpected default trust managers:" + Arrays.toString(trustManagers)); } x509TrustManager = (X509TrustManager) trustManagers[0]; // 这里传TLS或SSL其实都可以的 SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, new TrustManager[]{x509TrustManager}, new SecureRandom()); return new SSLConnectionSocketFactory(sslContext); } // https请求,不作证书校验 x509TrustManager = new X509TrustManager() { @Override public void checkClientTrusted(X509Certificate[] arg0, String arg1) { } @Override public void checkServerTrusted(X509Certificate[] arg0, String arg1) { // 不验证 } @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } }; SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, new TrustManager[]{x509TrustManager}, new SecureRandom()); return new SSLConnectionSocketFactory(sslContext); } /** * 获取(密钥及证书)仓库 * 注:该仓库用于存放 密钥以及证书 * * @param caInputStream * CA证书(此证书应由要访问的服务端提供) * @param cAalias * 别名 * 注意:别名应该是唯一的, 别名不要和其他的别名一样,否者会覆盖之前的相同别名的证书信息。别名即key-value中的key。 * @return 密钥、证书 仓库 * @throws KeyStoreException 异常信息 * @throws CertificateException 异常信息 * @throws IOException 异常信息 * @throws NoSuchAlgorithmException 异常信息 * @date 2019/6/11 18:48 */ private static KeyStore getKeyStore(InputStream caInputStream, String cAalias) throws KeyStoreException, CertificateException, IOException, NoSuchAlgorithmException { // 证书工厂 CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); // 秘钥仓库 KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); keyStore.load(null); keyStore.setCertificateEntry(cAalias, certificateFactory.generateCertificate(caInputStream)); return keyStore; }
/** * 根据是否是https请求,获取HttpClient客户端 * * TODO 本人这里没有进行完美封装。对于 校不校验校验证书的选择,本人这里是写死 * 在代码里面的,你们在使用时,可以灵活二次封装。 * * 提示: 此工具类的封装、相关客户端、服务端证书的生成,可参考我的这篇博客: * <linked>https://blog.csdn.net/justry_deng/article/details/91569132</linked> * * * @param isHttps 是否是HTTPS请求 * * @return HttpClient实例 * @date 2019/9/18 17:57 */private CloseableHttpClient getHttpClient(boolean isHttps) { CloseableHttpClient httpClient; if (isHttps) { SSLConnectionSocketFactory sslSocketFactory; try { /// 如果不作证书校验的话 sslSocketFactory = getSocketFactory(false, null, null); /// 如果需要证书检验的话 // 证书 //InputStream ca = this.getClass().getClassLoader().getResourceAsStream("client/ds.crt"); // 证书的别名,即:key。 注:cAalias只需要保证唯一即可,不过推荐使用生成keystore时使用的别名。 // String cAalias = System.currentTimeMillis() + "" + new SecureRandom().nextInt(1000); //sslSocketFactory = getSocketFactory(true, ca, cAalias); } catch (Exception e) { throw new RuntimeException(e); } httpClient = HttpClientBuilder.create().setSSLSocketFactory(sslSocketFactory).build(); return httpClient; } httpClient = HttpClientBuilder.create().build(); return httpClient;} /** * HTTPS辅助方法, 为HTTPS请求 创建SSLSocketFactory实例、TrustManager实例 * * @param needVerifyCa * 是否需要检验CA证书(即:是否需要检验服务器的身份) * @param caInputStream * CA证书。(若不需要检验证书,那么此处传null即可) * @param cAalias * 别名。(若不需要检验证书,那么此处传null即可) * 注意:别名应该是唯一的, 别名不要和其他的别名一样,否者会覆盖之前的相同别名的证书信息。别名即key-value中的key。 * * @return SSLConnectionSocketFactory实例 * @throws NoSuchAlgorithmException * 异常信息 * @throws CertificateException * 异常信息 * @throws KeyStoreException * 异常信息 * @throws IOException * 异常信息 * @throws KeyManagementException * 异常信息 * @date 2019/6/11 19:52 */private static SSLConnectionSocketFactory getSocketFactory(boolean needVerifyCa, InputStream caInputStream, String cAalias) throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException, KeyManagementException { X509TrustManager x509TrustManager; // https请求,需要校验证书 if (needVerifyCa) { KeyStore keyStore = getKeyStore(caInputStream, cAalias); TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); trustManagerFactory.init(keyStore); TrustManager[] trustManagers = trustManagerFactory.getTrustManagers(); if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) { throw new IllegalStateException("Unexpected default trust managers:" + Arrays.toString(trustManagers)); } x509TrustManager = (X509TrustManager) trustManagers[0]; // 这里传TLS或SSL其实都可以的 SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, new TrustManager[]{x509TrustManager}, new SecureRandom()); return new SSLConnectionSocketFactory(sslContext); } // https请求,不作证书校验 x509TrustManager = new X509TrustManager() { @Override public void checkClientTrusted(X509Certificate[] arg0, String arg1) { } @Override public void checkServerTrusted(X509Certificate[] arg0, String arg1) { // 不验证 } @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } }; SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, new TrustManager[]{x509TrustManager}, new SecureRandom()); return new SSLConnectionSocketFactory(sslContext);} /** * 获取(密钥及证书)仓库 * 注:该仓库用于存放 密钥以及证书 * * @param caInputStream * CA证书(此证书应由要访问的服务端提供) * @param cAalias * 别名 * 注意:别名应该是唯一的, 别名不要和其他的别名一样,否者会覆盖之前的相同别名的证书信息。别名即key-value中的key。 * @return 密钥、证书 仓库 * @throws KeyStoreException 异常信息 * @throws CertificateException 异常信息 * @throws IOException 异常信息 * @throws NoSuchAlgorithmException 异常信息 * @date 2019/6/11 18:48 */private static KeyStore getKeyStore(InputStream caInputStream, String cAalias) throws KeyStoreException, CertificateException, IOException, NoSuchAlgorithmException { // 证书工厂 CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); // 秘钥仓库 KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); keyStore.load(null); keyStore.setCertificateEntry(cAalias, certificateFactory.generateCertificate(caInputStream)); return keyStore;}