HttpClient請求https接口出現‘unable to find valid certification path to requested target’異常

背景

今天通過HttpClient請求一個外部接口時,出現SSLHandshakeException異常,通過查詢並解決了問題,現做記錄

  • HTTP POST方式調用外部接口
public class HttpClientUtil {
		public static JSONObject httpPost(String url, String strParam,String appid, String sign) throws Exception {
		// 針對http
		CloseableHttpClient httpClient = HttpClients.createDefault();
		JSONObject jsonResult = null;
		HttpPost httpPost = new HttpPost(url);
		RequestConfig requestConfig = RequestConfig.custom()
				.setSocketTimeout(10000).setConnectTimeout(10000).build();
		httpPost.setConfig(requestConfig);
		httpPost.addHeader("appid", appid);
		httpPost.addHeader("sign", sign);
		try {
			if (null != strParam) {
				StringEntity entity = new StringEntity(strParam,"utf-8");
				entity.setContentEncoding("UTF-8");
				entity.setContentType("application/json");
				httpPost.setEntity(entity);
			}
			CloseableHttpResponse result = httpClient.execute(httpPost);
			if (result.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				String str = "";
				try {
					str = EntityUtils.toString(result.getEntity(), "utf-8");
					jsonResult = JSONObject.parseObject(str);
				} catch (Exception e) {
					logger.error("post請求提交失敗:" + url, e);
				}
			}
		} catch (IOException e) {
			logger.error("post請求提交失敗:" + url, e);
		} finally {
			httpPost.releaseConnection();
		}
		return jsonResult;
	}
}
  • HTTPS POST方式調用外部接口

    • 在使用HttpClient完成對HTTPS 接口請求之前,還存在一個證書問題,需要將被調接口的證書下載並安裝到本地
    • 現已百度爲例:
      在這裏插入圖片描述
      在這裏插入圖片描述
      在這裏插入圖片描述
  • 選擇路徑並保存到本地

  • 在確保正確安裝了JDK之後,後以管理員方式打開CMD,並執行

keytool -import -file D://****.cer -keystore "%JAVA_HOME%\jre\lib\security\cacerts" -alias server
# `D://****.cer`: 證書保存路徑
# `server`:別名
  • 這裏還需要用到一個工具類
public class SSLClientCustom {
    private static final String HTTP = "http";

    private static final String HTTPS = "https";

    private static SSLConnectionSocketFactory sslConnectionSocketFactory = null;

    private static PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = null;
    
    private static SSLContextBuilder sslContextBuilder = null;
{
        try {
            sslContextBuilder = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
                @Override
                public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
                    return true;
                }
            });
            sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContextBuilder.build(), new String[]{"SSLv2Hello", "SSLv3", "TLSv1", "TLSv1.2"}, null, NoopHostnameVerifier.INSTANCE);
            Registry<ConnectionSocketFactory> registryBuilder = RegistryBuilder.<ConnectionSocketFactory>create()
                    .register(HTTP, new PlainConnectionSocketFactory())
                    .register(HTTPS, sslConnectionSocketFactory)
                    .build();
            poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(registryBuilder);
            poolingHttpClientConnectionManager.setMaxTotal(200);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }

    }
        public static CloseableHttpClient getHttpClinet() throws Exception {
        CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslConnectionSocketFactory)
                .setConnectionManager(poolingHttpClientConnectionManager)
                .setConnectionManagerShared(true)
                .build();
        return httpClient;
    }
}
  • 在創建httpClient時就需要發生變化
public class HttpClientUtil {
		public static JSONObject httpPost(String url, String strParam,String appid, String sign) throws Exception {
		// 針對https
		CloseableHttpClient httpClient = SSLClientCustom.getHttpClinet();
		JSONObject jsonResult = null;
		HttpPost httpPost = new HttpPost(url);
		RequestConfig requestConfig = RequestConfig.custom()
				.setSocketTimeout(10000).setConnectTimeout(10000).build();
		httpPost.setConfig(requestConfig);
		httpPost.addHeader("appid", appid);
		httpPost.addHeader("sign", sign);
		try {
			if (null != strParam) {
				StringEntity entity = new StringEntity(strParam,"utf-8");
				entity.setContentEncoding("UTF-8");
				entity.setContentType("application/json");
				httpPost.setEntity(entity);
			}
			CloseableHttpResponse result = httpClient.execute(httpPost);
			if (result.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				String str = "";
				try {
					str = EntityUtils.toString(result.getEntity(), "utf-8");
					jsonResult = JSONObject.parseObject(str);
				} catch (Exception e) {
					logger.error("post請求提交失敗:" + url, e);
				}
			}
		} catch (IOException e) {
			logger.error("post請求提交失敗:" + url, e);
		} finally {
			httpPost.releaseConnection();
		}
		return jsonResult;
	}
}

這樣就完成了使用HttpClient調用https接口的工作,若存在問題還望指正

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章