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 接口请求之前,还存在一个
证书
问题,需要将被调接口的证书下载并安装到本地 - 现已百度为例:
- 在使用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接口的工作,若存在问题还望指正