Java向指定URL发送请求出现net.ssl.SSLHandshakeException: PKIX path building failed异常
1. Java在做向指定 Url 发送 get 请求时报错
1.1 异常信息:javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
2. 原因分析
1. 网上搜的:google发现stackoverflow上不少人反应,twitter和新浪微博的api也会报这个异常,不少人反映客户端需要导入证书,其实大可不必,如果要导证书的话,用户不得哭了。。
2. 我是做WebSSO单点登录,要调到统一授权页面获取Xml信息,获取结果的时候报的错。
3. 用的第一种方式发送get请求,报这个错误!!!
/**
* 向指定的地址发送get请求
*
* @param url
* @return
*/
public static String getRequest(String url) {
try {
URL urlObj = new URL(url);
URLConnection connection = urlObj.openConnection();
InputStream is = connection.getInputStream();
byte[] b = new byte[1024];
int len;
StringBuilder sb = new StringBuilder();
while ((len = is.read(b)) != -1) {
sb.append(new String(b, 0, len));
}
return sb.toString();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
3. 换一种发送get请求,还是报这个错误!!!
添加项目依赖
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
测试方法
import java.io.IOException;
import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
public class SendGetRequest {
public static void main(String[] args) throws IOException {
// 向url发送GET请求
String url = "";
CloseableHttpClient httpClient = HttpClients.createDefault();
try {
HttpGet httpGet = new HttpGet(url);
CloseableHttpResponse httpResponse = httpClient.execute(httpGet);
try {
System.out.println(httpResponse.getStatusLine());
HttpEntity httpEntity = httpResponse.getEntity();
// 添加处理返回数据的代码
// 例如将返回的数据转换为字符串并输出
System.out.println(EntityUtils.toString(httpEntity));
EntityUtils.consume(httpEntity);
} finally {
httpResponse.close();
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
httpClient.close();
}
}
}
3. 解决方法
3.1 我的可能是单点登录统一授权的url有限制出现的问题,朋友们可以试下上面两种请求方式
3.2 手动导入证书到本地证书库(不推荐)
可以参考 导入证书
3.3 调整发生请求的代码,信任所有证书
1. trustAllHosts 该方法放任所以请求,不在校验时候有证书
/**
* Trust every server - dont check for any certificate
*/
private static void trustAllHosts() {
final String TAG = "trustAllHosts";
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[]{};
}
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
}};
// Install the all-trusting trust manager
try {
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
e.printStackTrace();
}
}
2. https.setHostnameVerifier(DO_NOT_VERIFY); 表示信任所有的证书
final static HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
3. 发送请求的代码
/**
* 向指定的地址发送get请求忽略证书
*
* @param httpUrl
* @return
*/
public static String httpGet(String httpUrl) {
BufferedReader input = null;
StringBuilder sb = null;
URL url = null;
HttpURLConnection con = null;
try {
url = new URL(httpUrl);
trustAllHosts();
HttpsURLConnection https = (HttpsURLConnection) url.openConnection();
if (url.getProtocol().toLowerCase().equals("https")) {
https.setHostnameVerifier(DO_NOT_VERIFY);
con = https;
} else {
con = (HttpURLConnection) url.openConnection();
}
input = new BufferedReader(new InputStreamReader(con.getInputStream()));
sb = new StringBuilder();
String s;
while ((s = input.readLine()) != null) {
sb.append(s).append("\n");
}
} catch (Exception e1) {
e1.printStackTrace();
} finally {
// close buffered
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// disconnecting releases the resources held by a connection so they may be closed or reused
if (con != null) {
con.disconnect();
}
}
return sb == null ? null : sb.toString();
}
final static HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
/**
* Trust every server - dont check for any certificate
*/
private static void trustAllHosts() {
final String TAG = "trustAllHosts";
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[]{};
}
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
}};
// Install the all-trusting trust manager
try {
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
e.printStackTrace();
}
}
3.4 完整的工具类代码
查看代码
package http;
import javax.net.ssl.*;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
/**
* 向url发送请求
*/
public class SendRequestUtil {
/**
* 向指定的地址发送get请求
*
* @param url
* @return
*/
public static String getRequest(String url) {
try {
URL urlObj = new URL(url);
URLConnection connection = urlObj.openConnection();
InputStream is = connection.getInputStream();
byte[] b = new byte[1024];
int len;
StringBuilder sb = new StringBuilder();
while ((len = is.read(b)) != -1) {
sb.append(new String(b, 0, len));
}
return sb.toString();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 向指定的地址发送post请求
*
* @param url url
* @param data 参数
* @return
*/
public static String postRequest(String url, String data) {
try {
URL urlObj = new URL(url);
URLConnection connection = urlObj.openConnection();
// 发送数据,把状态设置为可发送
connection.setDoOutput(true);
// 获取输出流
OutputStream os = connection.getOutputStream();
os.write(data.getBytes());
os.close();
InputStream is = connection.getInputStream();
byte[] b = new byte[1024];
int len;
StringBuilder sb = new StringBuilder();
while ((len = is.read(b)) != -1) {
sb.append(new String(b, 0, len));
}
return sb.toString();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 向指定的地址发送get请求忽略证书
*
* @param httpUrl
* @return
*/
public static String httpGet(String httpUrl) {
BufferedReader input = null;
StringBuilder sb = null;
URL url = null;
HttpURLConnection con = null;
try {
url = new URL(httpUrl);
trustAllHosts();
HttpsURLConnection https = (HttpsURLConnection) url.openConnection();
if (url.getProtocol().toLowerCase().equals("https")) {
https.setHostnameVerifier(DO_NOT_VERIFY);
con = https;
} else {
con = (HttpURLConnection) url.openConnection();
}
input = new BufferedReader(new InputStreamReader(con.getInputStream()));
sb = new StringBuilder();
String s;
while ((s = input.readLine()) != null) {
sb.append(s).append("\n");
}
} catch (Exception e1) {
e1.printStackTrace();
} finally {
// close buffered
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// disconnecting releases the resources held by a connection so they may be closed or reused
if (con != null) {
con.disconnect();
}
}
return sb == null ? null : sb.toString();
}
final static HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
/**
* Trust every server - dont check for any certificate
*/
private static void trustAllHosts() {
final String TAG = "trustAllHosts";
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[]{};
}
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
}};
// Install the all-trusting trust manager
try {
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
e.printStackTrace();
}
}
}