Java SSL 文件下载报错
需要:
筹备下载个文件, 是 https 的连贯, 浏览器没有问题。查看了下
org.apache.commons.io.FileUtils 工具类刚好有这个办法, 太省事了;
FileUtils.copyURLToFile(new URL(url), file);
果不其然报错了
javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative names matching IP address 47.114.190.241 found
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1946)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:316)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:310)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1639)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:223)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1037)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:965)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1064)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1367)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1395)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1379)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1564)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1492)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:263)
at java.net.URL.openStream(URL.java:1045)
at org.apache.commons.io.FileUtils.copyURLToFile(FileUtils.java:1478)
Caused by: java.security.cert.CertificateException: No subject alternative names matching IP address 47.114.190.241 found
at sun.security.util.HostnameChecker.matchIP(HostnameChecker.java:168)
at sun.security.util.HostnameChecker.match(HostnameChecker.java:94)
at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:455)
at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:436)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:200)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1621)
查看报错只须要批改 HostnameChecker 的 matchIP 办法就能够了
编写转换方法
private URL transUrl(String urlStr) {
// 用于高版本 JDK 跳过证书验证
TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() {public java.security.cert.X509Certificate[] getAcceptedIssuers() {return null;}
public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) { }
public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {}} };
// Activate the new trust manager
SSLContext sc = null;
try {sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
// 用于校验 SSL 的 IP
HostnameVerifier allHostsValid = new HostnameVerifier() {public boolean verify(String hostname, SSLSession session) {return true;}
};
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
// Open connection to the URL
URL url = new URL(urlStr);
URLConnection connection = url.openConnection();
return connection.getURL();} catch (Exception e) {throw new RuntimeException(e);
}
}
从新编写下载的代码
FileUtils.copyURLToFile(transUrl(url), file);
问题解决了