文件下载 SSLHandshakeException
Posted
技术标签:
【中文标题】文件下载 SSLHandshakeException【英文标题】:File Download SSLHandshakeException 【发布时间】:2016-09-30 11:35:30 【问题描述】:当我尝试使用 Java 代码以编程方式下载文件时,出现异常:
Exception in thread "main" 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:1949)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1509)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:914)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
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:1513)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1441)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
at java.net.URL.openStream(URL.java:1045)
at DownloadFileExample.download(DownloadFileExample.java:15)
at DownloadFileExample.main(DownloadFileExample.java:24)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Caused by: 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.validator.PKIXValidator.doBuild(PKIXValidator.java:387)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
at sun.security.validator.Validator.validate(Validator.java:260)
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1491)
... 20 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)
... 26 more
这是我的代码,包括我要下载的文件:
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
public class DownloadFileExample
public static void download(String downloadURL) throws IOException
URL website = new URL(downloadURL);
String fileName = "downloaded.zip";
try (InputStream inputStream = website.openStream())
Files.copy(inputStream, Paths.get(fileName), StandardCopyOption.REPLACE_EXISTING);
public static void main(String[] arguments) throws IOException
String downloadURL = "https://mh-nexus.de/downloads/HxDSetupEN.zip";
download(downloadURL);
我一开始尝试使用HTTP
协议下载,但它给了我301 moved permanently
状态码,所以我意识到它重定向到HTTPS
。但是,HTTPS
给了我上面的SSLHandshakeException
。使用浏览器,下载工作完美无缺。如何使用 Java 代码正确下载文件?
【问题讨论】:
您需要一个有效的证书才能通过您的代码下载它。 【参考方案1】:这是因为证书 https://mh-nexus.de 网站不在您的 JRE 的白名单中
选项
1) 将服务器证书包含在JRE白名单中(jre/lib/security/cacerts) 要下载服务器证书,请用浏览器打开站点,右键单击绿色锁,选择“查看证书”并下载
探索 cacerts 和导入可信证书的最简单方法是使用像 portecle (http://portecle.sourceforge.net/) 这样的 GUI 工具。你也可以使用keytool
keytool -import -trustcacerts -keystore /opt/java/jre/lib/security/cacerts -alias mycert -noprompt -storepass changeit -file /tmp/examplecert.crt
见How to properly import a selfsigned certificate into Java keystore that is available to all Java applications by default?
2) 使用您自己的信任库并包含服务器证书
System.setProperty ("javax.net.ssl.trustStore" path_to_your_cacerts_file);
3) 根本不使用信任库(BullyWiiPlaza 响应)
【讨论】:
【参考方案2】:好的,所以我找到了解决方案here。我只需要安装一个全信任的SSL
证书TrustManager
。虽然这通常不是一个好主意,但很适合我的目的。
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
public class DownloadFileExample
public static void download(String downloadURL) throws IOException
URL website = new URL(downloadURL);
String fileName = "downloaded.zip";
try (InputStream inputStream = website.openStream())
Files.copy(inputStream, Paths.get(fileName), StandardCopyOption.REPLACE_EXISTING);
private static void trustAllCertificates() throws NoSuchAlgorithmException, KeyManagementException
TrustManager[] trustManagers = new TrustManager[]new X509TrustManager()
public X509Certificate[] getAcceptedIssuers()
return new X509Certificate[0];
public void checkClientTrusted(
X509Certificate[] certs, String authType)
public void checkServerTrusted(
X509Certificate[] certs, String authType)
;
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustManagers, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
public static void main(String[] arguments) throws IOException, NoSuchAlgorithmException, KeyManagementException
trustAllCertificates();
String downloadURL = "https://mh-nexus.de/downloads/HxDSetupEN.zip";
download(downloadURL);
【讨论】:
以上是关于文件下载 SSLHandshakeException的主要内容,如果未能解决你的问题,请参考以下文章
Android 逆向Linux 文件分类 ( 普通文件 | 目录文件 | 链接文件 | 字符设备文件 | 管道文件 | 块设备文件 )
Android 逆向Linux 文件分类 ( 普通文件 | 目录文件 | 链接文件 | 字符设备文件 | 管道文件 | 块设备文件 )
背水一战 Windows 10 (85) - 文件系统: 获取文件夹和文件, 分组文件夹, 排序过滤文件夹和文件, 搜索文件