原文: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;}