Java 使用httpclient 调用Https 接口 PKIX path building failed 问题分析。
可能出现问题的原因
1.网站证书过期
2.网站证书没有配置齐全。
3.网站证书不是CA机构签发。
4.Java版本太老,证书库陈旧。
解决方案。
第一种:使用没有问题的证书。
第二种:将证书导入JDK下
(Lunix)具体步骤:
1. 将证书xxx.cer 复制到java安装目录 jre/lib/security 下。
2.运行如下命令 keytool -import -trustcacerts -alias 证书别名 -file 证书文件 -keystore cacerts -storepass changeit
#查看证书是否已经导入
keytool -list -alias 证书别名 -keystore cacerts -storepass changeit
#根据别名删除已经导入证书
keytool -delete -alias 证书别名 –keystore cacerts -storepass changeit
第三种:Java跳过https 检查
核心思想实现一个X509TrustManager接口,用于绕过验证
代码如下:
publicclassHttpsUtil{
/**
*绕过验证
*
*@return
*@throwsNoSuchAlgorithmException
*@throwsKeyManagementException
*/
publicstaticSSLContextcreateIgnoreVerifySSL()throwsNoSuchAlgorithmException,KeyManagementException{
SSLContextsc=SSLContext.getInstance("SSL");
//实现一个X509TrustManager接口,用于绕过验证,不用修改里面的方法
X509TrustManagertrustManager=newX509TrustManager(){
@Override
publicvoidcheckClientTrusted(
java.security.cert.X509Certificate[]paramArrayOfX509Certificate,
StringparamString)throwsCertificateException{
}
@Override
publicvoidcheckServerTrusted(
java.security.cert.X509Certificate[]paramArrayOfX509Certificate,
StringparamString)throwsCertificateException{
}
@Override
publicjava.security.cert.X509Certificate[]getAcceptedIssuers(){
returnnull;
}
};
sc.init(null,newTrustManager[]{
trustManager},null);
returnsc;
}
/**
*模拟请求
*
*@paramurl资源地址
*@parambody参数列表
*@paramencoding编码
*@return
*@throwsNoSuchAlgorithmException
*@throwsKeyManagementException
*@throwsIOException
*@throwsClientProtocolException
*/
publicstaticStringdoRequest(Stringurl,JSONObjectbody,Stringencoding,Stringmethod){
Stringresult="";
//采用绕过验证的方式处理https请求
try{
SSLContextsslcontext=createIgnoreVerifySSL();
//SSLContextsslcontext=SSLContext.getInstance("TLSv1.2");
//设置协议http和https对应的处理socket链接工厂的对象
Registry<ConnectionSocketFactory>socketFactoryRegistry=RegistryBuilder.<ConnectionSocketFactory>create()
.register("http",PlainConnectionSocketFactory.INSTANCE)
.register("https",newSSLConnectionSocketFactory(sslcontext))
.build();
PoolingHttpClientConnectionManagerconnManager=newPoolingHttpClientConnectionManager(socketFactoryRegistry);
HttpClients.custom().setConnectionManager(connManager);
//信任所有证书,关闭主机名校验
SSLConnectionSocketFactorysslsf=newSSLConnectionSocketFactory(
SSLContexts.custom().loadTrustMaterial(null,newTrustSelfSignedStrategy()).build(),
NoopHostnameVerifier.INSTANCE);
//创建Httpclient对象
CloseableHttpClientclient=HttpClients.custom().setSSLSocketFactory(sslsf).build();
HttpRequestBasehttpRequestBase=null;
if(method==null||method.isEmpty()||method.equals("POST")){
//创建post方式请求对象
HttpPosthttpPost=newHttpPost(url);
StringEntitys=newStringEntity(body.toJSONString(),"UTF-8");
//发送json数据需要设置contentType
s.setContentType("application/json");
httpPost.setEntity(s);//设置请求参数
装填参数
//List<NameValuePair>nvps=newArrayList<NameValuePair>();
//if(map!=null){
//for(Map.Entry<String,String>entry:map.entrySet()){
//nvps.add(newBasicNameValuePair(entry.getKey(),entry.getValue()));
//}
//}
设置参数到请求对象中
//httpPost.setEntity(newUrlEncodedFormEntity(nvps,encoding));
log.info("请求地址:"+url);
//设置header信息
//httpPost.setHeader("User-Agent","Mozilla/4.0(compatible;MSIE5.0;WindowsNT;DigExt)");
httpRequestBase=httpPost;
}else{
HttpGethttpGet=newHttpGet(url);
httpRequestBase=httpGet;
}
//指定报文头【Content-type】、【User-Agent】
httpRequestBase.setHeader("Content-type","application/json");
//执行请求操作,并拿到结果(同步阻塞)
CloseableHttpResponseresponse=client.execute(httpRequestBase);
//获取结果实体
HttpEntityentity=response.getEntity();
if(entity!=null){
//按指定编码转换结果实体为String类型
result=EntityUtils.toString(entity,encoding);
}
EntityUtils.consume(entity);
//释放链接
response.close();
returnresult;
}catch(Exceptione){
System.out.println(e);
returnnull;
}
}