使用HttpClient访问https 站点时,如果Java没有导入该站点的证书的话,则会报如下错误:
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
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1946)
因为Java在安装的时候,会默认导入某些根证书,所以有些网站不导入证书,也可以使用Java进行访问。
此外, Java的证书库和浏览器的证书管理是不同的机制, 所以即使在浏览器正常访问,使用Java语言的代码,比如HttpClient 进行访问时同样会出现上述的问题。
工具类
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.TrustStrategy;
import org.apache.http.util.EntityUtils;
import javax.net.ssl.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.*;
public class HttpUtils2 {
public static String postFile(String url, InputStream inputStream,String filename) throws Exception {
CloseableHttpClient httpClient = null;
CloseableHttpResponse response = null;
try{
HttpPost httpPost = new HttpPost(url);
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(60000)
.setSocketTimeout(60000)
.setConnectionRequestTimeout(60000)
.build();
httpPost.setConfig(requestConfig);
httpPost.setHeader("Content-Type",ContentType.MULTIPART_FORM_DATA.toString());
MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create().setMode(HttpMultipartMode.RFC6532);
multipartEntityBuilder.addBinaryBody("file",inputStream,ContentType.APPLICATION_OCTET_STREAM,filename);
HttpEntity httpEntity = multipartEntityBuilder.build();
httpPost.setEntity(httpEntity);
httpClient = createHttpClient(url);
response = httpClient.execute(httpPost);
HttpEntity responseEntity = response.getEntity();
return EntityUtils.toString(responseEntity,"UTF-8");
}catch (Exception ex){
throw ex;
}finally {
if(response != null){
response.close();
}
if(httpClient != null){
httpClient.close();
}
}
}
public static String postJson(String url,String jsonData) throws Exception {
CloseableHttpClient httpClient = null;
CloseableHttpResponse response = null;
try{
HttpPost httpPost = new HttpPost(url);
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(30000)
.setSocketTimeout(30000)
.setConnectionRequestTimeout(30000)
.build();
httpPost.setConfig(requestConfig);
StringEntity requestEntity = new StringEntity(jsonData,"UTF-8");
//requestEntity.setContentEncoding("UTF-8");
httpPost.setHeader("Content-type", "application/json");
httpPost.setEntity(requestEntity);
httpClient = createHttpClient(url);
response = httpClient.execute(httpPost);
HttpEntity responseEntity = response.getEntity();
return EntityUtils.toString(responseEntity,"UTF-8");
}catch (Exception ex){
throw ex;
}finally {
if(response != null){
response.close();
}
if(httpClient != null){
httpClient.close();
}
}
}
public static String httpPost(String url, HashMap postData, HashMap header) throws Exception {
CloseableHttpClient httpClient = null;
CloseableHttpResponse response = null;
try{
HttpPost httpPost = new HttpPost(url);
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(30000)
.setSocketTimeout(30000)
.setConnectionRequestTimeout(30000)
.build();
httpPost.setConfig(requestConfig);
if(header != null){
header.forEach(
(k,v) -> httpPost.setHeader(String.valueOf(k),String.valueOf(v))
);
}
List<NameValuePair> params = new ArrayList<>();
if(postData != null){
postData.forEach(
(k,v)-> params.add(new BasicNameValuePair(String.valueOf(k),String.valueOf(v)))
);
}
HttpEntity requestEntity = new UrlEncodedFormEntity(params,"UTF-8");
httpPost.setEntity(requestEntity);
httpClient = createHttpClient(url);
response = httpClient.execute(httpPost);
HttpEntity responseEntity = response.getEntity();
return EntityUtils.toString(responseEntity,"UTF-8");
}catch (Exception ex){
throw ex;
}finally {
if(response != null){
response.close();
}
if(httpClient != null){
httpClient.close();
}
}
}
public static String httpPost(String url,HashMap postData) throws Exception{
return httpPost(url,postData,null);
}
public static String httpPost(String url)throws Exception {
return httpPost(url,null);
}
public static String httpGet(String url,HashMap header) throws Exception {
CloseableHttpClient httpClient = null;
CloseableHttpResponse response = null;
try{
HttpGet httpGet = new HttpGet(url);
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(30000)
.setSocketTimeout(30000)
.setConnectionRequestTimeout(30000)
.build();
httpGet.setConfig(requestConfig);
if(header != null){
header.forEach(
(k,v) -> httpGet.setHeader(String.valueOf(k),String.valueOf(v))
);
}
httpClient = createHttpClient(url);
response = httpClient.execute(httpGet);
HttpEntity responseEntity = response.getEntity();
return EntityUtils.toString(responseEntity,"UTF-8");
}catch (Exception ex){
throw ex;
}finally {
if(response != null){
response.close();
}
if(httpClient != null){
httpClient.close();
}
}
}
public static String httpGet(String url) throws Exception{
return httpGet(url,null);
}
/**
* 发送https请求
* @param url url
* @param requestMethod 请求方式
* @param param 请求参数
* @return 返回值
*/
public static HttpsURLConnection sendHttpsRequest(String url, String requestMethod, String param) {
StringBuilder result = new StringBuilder();
HttpsURLConnection conn = null;
try {
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, new TrustManager[]{
new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
}, new SecureRandom());
URL console = new URL(url);
conn = (HttpsURLConnection) console.openConnection();
// GET/POST
conn.setRequestMethod(requestMethod);
conn.setRequestProperty("Content-Type", "application/json");
conn.setDoOutput(true);
conn.setDoInput(true);
if (null != param) {
OutputStream outputStream = conn.getOutputStream();
// 注意编码格式
outputStream.write(param.getBytes("UTF-8"));
outputStream.close();
}
// 设置证书忽略相关操作
conn.setSSLSocketFactory(sc.getSocketFactory());
conn.setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String s, SSLSession sslSession) {
return true;
}
});
conn.connect();
return conn;
} catch (NoSuchAlgorithmException | KeyManagementException | MalformedURLException e) {
e.printStackTrace();
} catch (IOException ioException) {
ioException.printStackTrace();
}
return null;
}
// http协议访问方法
public static HttpURLConnection sendHttpRequest(String url, String requestMethod, String param) {
StringBuilder result = new StringBuilder();
HttpURLConnection conn = null;
try {
URL console = new URL(url);
conn = (HttpURLConnection) console.openConnection();
// GET/POST
conn.setRequestMethod(requestMethod);
conn.setRequestProperty("Content-Type", "application/json");
conn.setDoOutput(true);
conn.setDoInput(true);
if (null != param) {
OutputStream outputStream = conn.getOutputStream();
// 注意编码格式
outputStream.write(param.getBytes("UTF-8"));
outputStream.close();
}
conn.connect();
// InputStream is = conn.getInputStream();
// BufferedReader br = new BufferedReader(new InputStreamReader(is));
// String ret = "";
// while ((ret = br.readLine()) != null) {
// if (ret != null && !ret.trim().equals("")) {
// result.append(new String(ret.getBytes("utf-8"), "utf-8"));
// }
// }
// conn.disconnect();
// br.close();
} catch (IOException ioException) {
ioException.printStackTrace();
}
return conn;
}
/***
* 获取httpUrl问号后面的参数
* @param httpUrl
* @return
*/
public static Map<String,String> getUrlParam(String httpUrl){
Map<String,String> paramMap = new LinkedHashMap<>();
String[] urlParam = httpUrl.split("\\?");
if (urlParam.length < 1){
return paramMap;
}
String query = urlParam[1];
for (String param : query.split("&")){
String[] pair = param.split("=");
String key = pair[0].toLowerCase(Locale.ROOT);
String value = "";
if (pair.length > 1) {
value = pair[1];
}
paramMap.put(key,value);
}
return paramMap;
}
/**
* HttpClient 信任所有的站点
* @param url
* @return
* @throws Exception
*/
public static CloseableHttpClient createHttpClient(String url) throws Exception {
if(isHttpsUrl(url)) {
//创建SSL的上下文,类型是SSLContext,该上下文中设置信任策略,信任所有的站点
SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
@Override
public boolean isTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) throws java.security.cert.CertificateException {
return true;
}
}).build();
//基于SSL的上下文,创建SSL连接的套接字工厂对象SSLConnectionSocketFactory
SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext,
NoopHostnameVerifier.INSTANCE);
//使用SSLConnectionSocketFactory作为参数,来构建信任所有站点的HttpClient对象
CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslSocketFactory).build();
return httpclient;
}
return HttpClients.createDefault();
}
/**
* 判断是否https 开始的地址
* @param val
* @return
*/
public static boolean isHttpsUrl(String val) {
String regex = "^(https)://[a-zA-Z0-9.-]+(:\\d+)?(/.*)?$";
return val.matches(regex);
}
}
最后