连接到 HTTPS 站点时出现 SSLHandshakeException

Posted

技术标签:

【中文标题】连接到 HTTPS 站点时出现 SSLHandshakeException【英文标题】:SSLHandshakeException while connecting to HTTPS site 【发布时间】:2020-04-30 07:27:14 【问题描述】:

我在 Java HttpsURLConnection 中创建。我从网站下载了证书并使用此证书创建了文件 truststore.jks。我的应用程序正在从 truststore.jks 获取证书并连接到网站。它可以工作......在我的电脑上。但是在服务器上部署应用程序后,我得到了这个丑陋的异常:

Cause: 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

Stack trace:
[sun.security.ssl.Alerts.getSSLException(Unknown Source)
 sun.security.ssl.SSLSocketImpl.fatal(Unknown Source)
 sun.security.ssl.Handshaker.fatalSE(Unknown Source)
 sun.security.ssl.Handshaker.fatalSE(Unknown Source)
 sun.security.ssl.ClientHandshaker.serverCertificate(Unknown Source)
 sun.security.ssl.ClientHandshaker.processMessage(Unknown Source)
 sun.security.ssl.Handshaker.processLoop(Unknown Source)
 sun.security.ssl.Handshaker.process_record(Unknown Source)
 sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source)
 sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
 sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
 sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
 sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)
 sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
 sun.net.www.protocol.http.HttpURLConnection.getInputStream0(Unknown Source)
 sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
 sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(Unknown Source)

我在 ConnectionFactory 类中创建 HttpsURLConnection,并运行 connection.getInputStream() 方法。

ConnectionFactory.java:

public final class ConnectionFactory 

    public HttpsURLConnection getHttpsURLConnection(URL url, String trustStorePath, String trustStorePassword)
            throws FileTransferWorkerException 
        KeyStore keyStore = loadKeyStore(trustStorePath, trustStorePassword);
        TrustManagerFactory trustManagerFactory = initTrustManagerFactory(keyStore);
        SSLSocketFactory sslSocketFactory = buildSSLSocketFactory(trustManagerFactory);
        return buildConnection(url, sslSocketFactory);
    

    private KeyStore loadKeyStore(String path, String password) throws FileTransferWorkerException 
        KeyStore keystore;
        try 
            keystore = KeyStore.getInstance("JKS");
         catch (KeyStoreException e) 
            throw new FileTransferWorkerException(e);
        

        try (FileInputStream fileInputStream = new FileInputStream(path)) 
            keystore.load(fileInputStream, password.toCharArray());
         catch (IOException | CertificateException | NoSuchAlgorithmException e) 
            throw new FileTransferWorkerException("Can not load keyStore from " + path, e);
        

        return keystore;
    

    private TrustManagerFactory initTrustManagerFactory(KeyStore keyStore) throws FileTransferWorkerException 
        TrustManagerFactory trustManagerFactory;

        try 
            trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
         catch (NoSuchAlgorithmException e) 
            throw new FileTransferWorkerException(e);
        

        try 
            trustManagerFactory.init(keyStore);
         catch (KeyStoreException e) 
            throw new FileTransferWorkerException(e);
        

        return trustManagerFactory;
    

    private SSLSocketFactory buildSSLSocketFactory(TrustManagerFactory trustManagerFactory) throws FileTransferWorkerException 
        SSLContext sslContext;
        try 
            sslContext = SSLContext.getInstance("TLS");
         catch (NoSuchAlgorithmException e) 
            throw new FileTransferWorkerException(e);
        

        try 
            sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
         catch (KeyManagementException e) 
            throw new FileTransferWorkerException(e);
        

        return sslContext.getSocketFactory();
    

    private HttpsURLConnection buildConnection(URL url, SSLSocketFactory sslSocketFactory) throws FileTransferWorkerException 
        HttpsURLConnection connection;

        try 
            connection = (HttpsURLConnection) url.openConnection();
         catch (IOException e) 
            throw new FileTransferWorkerException("Can not connect to " + url.getPath(), e);
        

        connection.setSSLSocketFactory(sslSocketFactory);
        return connection;
    

和调用方法:

 private void download(URL url, String trustStorePath, String trustStorePassword, File file)
            throws IOException, FileTransferWorkerException 
        HttpsURLConnection connection = new ConnectionFactory().getHttpsURLConnection(url, trustStorePath, trustStorePassword);
        try (ReadableByteChannel reader = Channels.newChannel(connection.getInputStream())
            ...
         finally 
            connection.disconnect();
        
    

我需要使用我的 truststor.jks 文件,而不是 cacerts。你有什么想法我犯了错误吗?帮助。

【问题讨论】:

因此您可以在本地加载证书,但不能在部署后加载。 JKS 文件是否包含在存档中? 对不起,我不明白。你是什​​么意思“存档”?我在服务器上部署了jks文件 ".war", ".jar", ... 用于部署在服务器上的 java 存档 不,它不在 jar 中 【参考方案1】:

我想通了。在本地,我连接到我公司的网络并且我有他们的证书(因为代理)。但是服务器没有使用代理,应该有来自端点服务器的真实证书。

【讨论】:

以上是关于连接到 HTTPS 站点时出现 SSLHandshakeException的主要内容,如果未能解决你的问题,请参考以下文章

通过 HTTPS 连接到 MobileFirst Server 时出现问题

在 Mac OSx 上通过 SSH 连接到 EC2 时出现权限错误

连接到共享点时出现 Power BI 错误

连接到我的 api 时出现电子内容安全策略错误

尝试连接到 AWS Gateway 私有 API 时出现 UnknownHostException

将 ASValueTrackingSlider 连接到我的代码时出现未知错误