错误描述:
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
解决办法:
方案一:
增加一个自己的https协议类 MySSLSocketFactory.java
类如下:
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.SocketFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.commons.httpclient.ConnectTimeoutException;
import org.apache.commons.httpclient.params.HttpConnectionParams;
import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
public class MySSLSocketFactory implements ProtocolSocketFactory {
static {
System.out.println(">>>>in MySSLSocketFactory>>");
}
private SSLContext sslcontext = null;
private SSLContext createSSLContext() {
SSLContext sslcontext = null;
try {
sslcontext = SSLContext.getInstance("SSL");
sslcontext.init(null,
new TrustManager[] { new TrustAnyTrustManager() },
new java.security.SecureRandom());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
return sslcontext;
}
private SSLContext getSSLContext() {
if (this.sslcontext == null) {
this.sslcontext = createSSLContext();
}
return this.sslcontext;
}
public Socket createSocket(Socket socket, String host, int port,
boolean autoClose) throws IOException, UnknownHostException {
return getSSLContext().getSocketFactory().createSocket(socket, host,
port, autoClose);
}
public Socket createSocket(String host, int port) throws IOException,
UnknownHostException {
return getSSLContext().getSocketFactory().createSocket(host, port);
}
public Socket createSocket(String host, int port, InetAddress clientHost,
int clientPort) throws IOException, UnknownHostException {
return getSSLContext().getSocketFactory().createSocket(host, port,
clientHost, clientPort);
}
public Socket createSocket(String host, int port, InetAddress localAddress,
int localPort, HttpConnectionParams params) throws IOException,
UnknownHostException, ConnectTimeoutException {
if (params == null) {
throw new IllegalArgumentException("Parameters may not be null");
}
int timeout = params.getConnectionTimeout();
SocketFactory socketfactory = getSSLContext().getSocketFactory();
if (timeout == 0) {
return socketfactory.createSocket(host, port, localAddress,
localPort);
} else {
Socket socket = socketfactory.createSocket();
SocketAddress localaddr = new InetSocketAddress(localAddress,
localPort);
SocketAddress remoteaddr = new InetSocketAddress(host, port);
socket.bind(localaddr);
socket.connect(remoteaddr, timeout);
return socket;
}
}
private static class TrustAnyTrustManager implements X509TrustManager {
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[] {};
}
}
}
请求类:
/**
*
*/
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.httpclient.protocol.Protocol;
import org.apache.commons.httpclient.util.URIUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @author nassir wen
* @data 2012-3-31 下午05:09:13
* @version V2.5
* @Company: MSD.
* @Copyright Copyright (c) 2012
*/
public class HttpsRequest {
private static final Logger logger = LoggerFactory.getLogger(HttpsRequest.class);
/**
*
* @param url
* @return
*/
public static String post(String url) {
//增加下面两行代码
Protocol myhttps = new Protocol("https", new MySSLSocketFactory(), 443);
Protocol.registerProtocol("https", myhttps);
HttpClient client = new HttpClient();
HttpMethod post = new PostMethod(url);
try {
client.executeMethod(post);
byte[] responseBody = post.getResponseBody();
String result = new String(responseBody,"GBK");
return result;
} catch (HttpException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
post.releaseConnection();
}
return null;
}
/**
* 执行一个HTTP GET请求,返回请求响应的HTML
*
* @param url 请求的URL地址
* @return 返回请求响应的HTML
*/
public static int doGet(String url) {
//增加下面两行代码
Protocol myhttps = new Protocol("https", new MySSLSocketFactory(), 443);
Protocol.registerProtocol("https", myhttps);
HttpClient client = new HttpClient();
HttpMethod method = new GetMethod(url);
try {
client.executeMethod(method);
} catch (URIException e) {
logger.error("执行HTTP Get请求时,发生异常!", e);
return HttpStatus.SC_BAD_REQUEST;
} catch (IOException e) {
logger.error("执行HTTP Get请求" + url + "时,发生异常!", e);
return HttpStatus.SC_BAD_REQUEST;
} finally {
method.releaseConnection();
}
logger.info("执行HTTP GET请求,返回码: {}", method.getStatusCode());
return method.getStatusCode();
}
/**
* 执行一个带参数的HTTP GET请求,返回请求响应的JSON字符串
*
* @param url 请求的URL地址
* @return 返回请求响应的JSON字符串
*/
public static String doGet(String url, String param) {
//增加下面两行代码
Protocol myhttps = new Protocol("https", new MySSLSocketFactory(), 443);
Protocol.registerProtocol("https", myhttps);
// 构造HttpClient的实例
HttpClient client = new HttpClient();
//设置参数
// 创建GET方法的实例
GetMethod method = new GetMethod(url + "?" + param);
// 使用系统提供的默认的恢复策略
method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
new DefaultHttpMethodRetryHandler());
try {
// 执行getMethod
client.executeMethod(method);
if (method.getStatusCode() == HttpStatus.SC_OK) {
BufferedReader reader = new BufferedReader(new InputStreamReader(
method.getResponseBodyAsStream(), "UTF-8"));
String tempLine = "";
StringBuffer resultBuffer = new StringBuffer();
while ((tempLine = reader.readLine()) != null) {
resultBuffer.append(tempLine).append(System.getProperty("line.separator"));
}
return resultBuffer.toString();
}
} catch (IOException e) {
logger.error("执行HTTP Get请求" + url + "时,发生异常!", e);
} finally {
method.releaseConnection();
}
return null;
}
/**
* 执行一个HTTP GET请求,返回请求响应的HTML
*
* @param url 请求的URL地址
* @param queryString 请求的查询参数,可以为null
* @param charset 字符集
* @param pretty 是否美化
* @return 返回请求响应的HTML
*/
public static String doGet(String url, String queryString, String charset, boolean pretty) {
//logger.info("http的请求地址为:"+url);
logger.info("http的请求参数为:" + queryString);
//增加下面两行代码
Protocol myhttps = new Protocol("https", new MySSLSocketFactory(), 443);
Protocol.registerProtocol("https", myhttps);
StringBuffer response = new StringBuffer();
HttpClient client = new HttpClient();
HttpMethod method = new GetMethod(url);
try {
if (StringUtils.isNotBlank(queryString)) {
method.setQueryString(URIUtil.encodeQuery(queryString));
}
HttpConnectionManagerParams managerParams = client.getHttpConnectionManager().getParams();
// 设置连接的超时时间
managerParams.setConnectionTimeout(3 * 60 * 1000);
// 设置读取数据的超时时间
managerParams.setSoTimeout(5 * 60 * 1000);
client.executeMethod(method);
logger.info("http的请求地址为:" + url + ",返回的状态码为" + method.getStatusCode());
BufferedReader reader = new BufferedReader(new InputStreamReader(method.getResponseBodyAsStream(), charset));
String line;
while ((line = reader.readLine()) != null) {
if (pretty) {
response.append(line).append(System.getProperty("line.separator"));
} else {
response.append(line);
}
}
reader.close();
} catch (Exception e) {
logger.error("执行HTTP Get请求" + url + "时,发生异常!" + e);
return response.toString();
} finally {
method.releaseConnection();
}
return response.toString();
}
/**
* 执行一个带参数的HTTP POST请求,返回请求响应的JSON字符串
*
* @param url 请求的URL地址
* @param map 请求的map参数
* @return 返回请求响应的JSON字符串
*/
public static String doPost(String url, Map<String, Object> map) {
//增加下面两行代码
Protocol myhttps = new Protocol("https", new MySSLSocketFactory(), 443);
Protocol.registerProtocol("https", myhttps);
// 构造HttpClient的实例
HttpClient httpClient = new HttpClient();
// 创建POST方法的实例
PostMethod method = new PostMethod(url);
// 这个basicNameValue**放在List中
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
// 创建basicNameValue***对象参数
if (map != null) {
for (Map.Entry<String, Object> entry : map.entrySet()) {
nameValuePairs.add(new NameValuePair(entry.getKey(), entry.getValue().toString()));
}
}
// 填入各个表单域的值
NameValuePair[] param = nameValuePairs.toArray(new NameValuePair[nameValuePairs.size()]);
method.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
// 将表单的值放入postMethod中
method.addParameters(param);
try {
// 执行postMethod
int statusCode = httpClient.executeMethod(method);
if (method.getStatusCode() == HttpStatus.SC_OK) {
BufferedReader reader = new BufferedReader(new InputStreamReader(
method.getResponseBodyAsStream(), "UTF-8"));
String tempLine = "";
StringBuffer resultBuffer = new StringBuffer();
while ((tempLine = reader.readLine()) != null) {
resultBuffer.append(tempLine).append(System.getProperty("line.separator"));
}
return resultBuffer.toString();
}
} catch (UnsupportedEncodingException e1) {
logger.error(e1.getMessage());
} catch (IOException e) {
logger.error("执行HTTP Post请求" + url + "时,发生异常!" + e.toString());
} finally {
method.releaseConnection();
}
return null;
}
/**
* 执行一个HTTP POST请求,返回请求响应的HTML
*
* @param url 请求的URL地址
* @param reqStr 请求的查询参数,可以为null
* @param charset 字符集
* @return 返回请求响应的HTML
*/
public static String doPost(String url, String reqStr, String contentType, String charset) {
//增加下面两行代码
Protocol myhttps = new Protocol("https", new MySSLSocketFactory(), 443);
Protocol.registerProtocol("https", myhttps);
HttpClient client = new HttpClient();
PostMethod method = new PostMethod(url);
try {
HttpConnectionManagerParams managerParams = client
.getHttpConnectionManager().getParams();
managerParams.setConnectionTimeout(30000); // 设置连接超时时间(单位毫秒)
managerParams.setSoTimeout(30000); // 设置读数据超时时间(单位毫秒)
method.setRequestEntity(new StringRequestEntity(reqStr, contentType, "utf-8"));
client.executeMethod(method);
logger.info("返回的状态码为" + method.getStatusCode());
if (method.getStatusCode() == HttpStatus.SC_OK) {
BufferedReader reader = new BufferedReader(new InputStreamReader(
method.getResponseBodyAsStream(), "UTF-8"));
String tempLine = "";
StringBuffer resultBuffer = new StringBuffer();
while ((tempLine = reader.readLine()) != null) {
resultBuffer.append(tempLine).append(System.getProperty("line.separator"));
}
return resultBuffer.toString();
}
} catch (UnsupportedEncodingException e1) {
logger.error(e1.getMessage());
return "";
} catch (IOException e) {
logger.error("执行HTTP Post请求" + url + "时,发生异常!" + e.toString());
return "";
} finally {
method.releaseConnection();
}
return null;
}
/**
* @param url
* @param entity
* @return
* @throws IOException
*/
public static String doPost(String url, HttpEntity entity) {
//增加下面两行代码
Protocol myhttps = new Protocol("https", new MySSLSocketFactory(), 443);
Protocol.registerProtocol("https", myhttps);
//创建httpclient对象
CloseableHttpClient client = HttpClients.createSystem();
//创建post方式请求对象
HttpPost httpPost = new HttpPost(url);
//设置参数到请求对象中
httpPost.setEntity(entity);
BufferedReader reader = null;
try {
CloseableHttpResponse response = client.execute(httpPost);
logger.info("Status:" + response.getStatusLine().getStatusCode());
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
String inputLine;
StringBuffer buffer = new StringBuffer();
while ((inputLine = reader.readLine()) != null) {
buffer.append(inputLine);
}
reader.close();
return buffer.toString();
}
} catch (IOException ex) {
logger.info("执行http post请求出错,exception={}", ex.getMessage());
} finally {
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
}
测试:
@Test
public void testHttp1(){
System.out.println(HttpsRequest.post("https://www.alipay.com"));//支付宝做测试
}
@Test
public void testdoGet(){
System.out.println(HttpsRequest.doGet("https://www.alipay.com","11111"));//支付宝做测试
}
方案二:
使用HttpClient
类如下:
/**
* @author zys
* @date 2020/4/22 16:59
*/
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import com.fadada.sdk.util.http.SSLClient;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
/*
* 利用HttpClient进行post请求的工具类
*/
public class HttpClientUtil {
public static String doPost(String url,Map<String,String> map,String charset){
HttpClient httpClient = null;
HttpPost httpPost = null;
String result = null;
try{
httpClient = new SSLClient();
httpPost = new HttpPost(url);
//设置参数
List<NameValuePair> list = new ArrayList<NameValuePair>();
Iterator iterator = map.entrySet().iterator();
while(iterator.hasNext()){
Entry<String,String> elem = (Entry<String, String>) iterator.next();
list.add(new BasicNameValuePair(elem.getKey(),elem.getValue()));
}
if(list.size() > 0){
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list,charset);
httpPost.setEntity(entity);
}
HttpResponse response = httpClient.execute(httpPost);
if(response != null){
HttpEntity resEntity = response.getEntity();
if(resEntity != null){
result = EntityUtils.toString(resEntity,charset);
}
}
}catch(Exception ex){
ex.printStackTrace();
}
return result;
}
}
测试
@Test
public void testHttpClientUtil(){
String url = "https://www.alipay.com";
String charset = "utf-8";
Map<String,String> createMap = new HashMap<String,String>();
createMap.put("param","****");
String httpOrgCreateTestRtn = HttpClientUtil.doPost(url,createMap,charset);
System.out.println("result:"+httpOrgCreateTestRtn);
}
说明:
参考:1.https://www.cnblogs.com/it-wangzhen/p/9228953.html
2.https://www.cnblogs.com/gisblogs/p/4626260.html
3.加上自己的理解和应用,综合链接1和2得到的
本人公众号(烂笔头写代码):
1.欢迎关注,如果需要什么请留言。
2.公众号特色:本人记性不好,就经常把开发中通用的,可直接拿来就用的。做了笔记。如需自取,不定时更新。关于Linux、spring相关、算法等。