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