最近在工作中调用一个借口,需要用到https.ssl请求,前任开发人员留下的https请求工具类不适用,报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
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错误,因此在网上搜寻原因。大都说是就是安全java自带的安全证书不受信任,一是安装证书,感觉略麻烦,另外一种是通过代码程序实现。本人讲述第二种方法,可以快速解决问题。
直接调用方法即可,方便快捷,我的业务是获取token,请求入口是:
String url = "https://ssl.logink.org/;
String param = "userid="+userId+"&password="+password+"&resource="+containerResource;
String token="";
try {
SslRequest st = new SslRequest();
String html = st.postRequest(url, param, 3000);
System.out.println(html);
JSONObject jsonObject = JSONObject.fromObject(html);
token = jsonObject.getString("token");
} catch (Exception e) {
e.printStackTrace();
}
调用的是封装好的方法postRequest(url, param, 3000);
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.URLConnection;
import org.apache.commons.io.IOUtils;
public class SslRequest {
public String getRequest(String url,int timeOut) throws Exception{
URL u = new URL(url);
if("https".equalsIgnoreCase(u.getProtocol())){
SslUtils.ignoreSsl();
}
URLConnection conn = u.openConnection();
conn.setConnectTimeout(timeOut);
conn.setReadTimeout(timeOut);
return IOUtils.toString(conn.getInputStream());
}
public String postRequest(String urlAddress,String args,int timeOut) throws Exception{
URL url = new URL(urlAddress);
if("https".equalsIgnoreCase(url.getProtocol())){
SslUtils.ignoreSsl();
}
URLConnection u = url.openConnection();
u.setDoInput(true);
u.setDoOutput(true);
u.setConnectTimeout(timeOut);
u.setReadTimeout(timeOut);
OutputStreamWriter osw = new OutputStreamWriter(u.getOutputStream(), "UTF-8");
osw.write(args);
osw.flush();
osw.close();
u.getOutputStream();
return IOUtils.toString(u.getInputStream());
}
}
解决异常的根本在下面这个类的方法,直接调用即可
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
public class SslUtils {private static void trustAllHttpsCertificates() throws Exception {
TrustManager[] trustAllCerts = new TrustManager[1];
TrustManager tm = new miTM();
trustAllCerts[0] = tm;
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, null);
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
}
static class miTM implements TrustManager,X509TrustManager {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public boolean isServerTrusted(X509Certificate[] certs) {
return true;
}
public boolean isClientTrusted(X509Certificate[] certs) {
return true;
}
public void checkServerTrusted(X509Certificate[] certs, String authType)
throws CertificateException {
return;
}
public void checkClientTrusted(X509Certificate[] certs, String authType)
throws CertificateException {
return;
}
}
/**
* 忽略HTTPS请求的SSL证书,必须在openConnection之前调用
* @throws Exception
*/
public static void ignoreSsl() throws Exception{
HostnameVerifier hv = new HostnameVerifier() {
public boolean verify(String urlHostName, SSLSession session) {
System.out.println("Warning: URL Host: " + urlHostName + " vs. " + session.getPeerHost());
return true;
}
};
trustAllHttpsCertificates();
HttpsURLConnection.setDefaultHostnameVerifier(hv);
}
}
不管怎样问题先解决了,有更好的方法的话可以交流一下。