如何解决javax.net.ssl.SSLHandshakeException错误?

问题描述 投票:91回答:6

我已与VPN连接,以设置广告资源API来获取产品列表,并且效果很好。一旦我从Web服务获得结果并绑定到UI。当我遇到付款错误时,我也将PayPal与我的make Express结帐应用程序集成在一起。我将servlet用于后端过程。谁能说出解决此问题的方法?

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 servlets paypal vpn sslhandshakeexception
6个回答
135
投票

首先,您需要从尝试连接的服务器获取公共证书。这可以通过多种方式完成,例如联系服务器管理员并要求输入using OpenSSL to download it,或者由于这似乎是HTTP服务器,因此可以通过任何浏览器连接到该服务器,查看页面的安全信息,以及保存证书的副本。 (Google应该能够准确告诉您如何使用特定的浏览器。)

现在您已将证书保存在文件中,您需要将其添加到JVM的信任库中。 JRE的$JAVA_HOME/jre/lib/security/或JDK的$JAVA_HOME/lib/security处有一个名为cacerts的文件,该文件随Java一起提供,其中包含著名的证书颁发机构的公共证书。要导入新证书,请以具有写cacerts权限的用户身份运行keytool:

keytool -import -file <the cert file> -alias <some meaningful name> -keystore <path to cacerts file>

它很可能会要求您输入密码。 Java随附的默认密码为changeit。几乎没有人更改它。在完成了这些相对简单的步骤之后,您将安全地进行通信,并确保与正确的服务器且仅与正确的服务器通信(只要它们不会丢失其私钥)。


15
投票

现在我以这种方式解决了这个问题,

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.OutputStream; 

// Create a trust manager that does not validate certificate chains like the default 

TrustManager[] trustAllCerts = new TrustManager[]{
        new X509TrustManager() {

            public java.security.cert.X509Certificate[] getAcceptedIssuers()
            {
                return null;
            }
            public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType)
            {
                //No need to implement.
            }
            public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType)
            {
                //No need to implement.
            }
        }
};

// Install the all-trusting trust manager
try 
{
    SSLContext sc = SSLContext.getInstance("SSL");
    sc.init(null, trustAllCerts, new java.security.SecureRandom());
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} 
catch (Exception e) 
{
    System.out.println(e);
}

当然,此解决方案仅应在无法使用keytool安装所需证书的情况下使用,例如使用临时证书进行本地测试。


10
投票

[只要我们尝试连接到URL,

如果另一个站点的服务器正在运行https协议,并要求我们通过证书中提供的信息进行通信,则我们有以下选择:

1)索取证书(下载证书),并以trustore的形式导入此证书。可以在\ Java \ jdk1.6.0_29 \ jre \ lib \ security \ cacerts中找到默认的trustore Java使用,然后如果我们重试连接到URL连接,将被接受。

2)在正常业务情况下,我们可能正在连接到组织中的内部URL,我们知道它们是正确的。在这种情况下,您相信它是正确的URL。在上述情况下,可以使用不强制存储证书以连接到特定URL的代码。

对于第二点,我们必须遵循以下步骤:

1)编写下面的方法,该方法为HttpsURLConnection设置HostnameVerifier,在所有情况下均返回true,这表示我们信任trustStore。

  // trusting all certificate 
 public void doTrustToCertificates() throws Exception {
        Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
        TrustManager[] trustAllCerts = new TrustManager[]{
                new X509TrustManager() {
                    public X509Certificate[] getAcceptedIssuers() {
                        return null;
                    }

                    public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
                        return;
                    }

                    public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException {
                        return;
                    }
                }
        };

        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        HostnameVerifier hv = new HostnameVerifier() {
            public boolean verify(String urlHostName, SSLSession session) {
                if (!urlHostName.equalsIgnoreCase(session.getPeerHost())) {
                    System.out.println("Warning: URL host '" + urlHostName + "' is different to SSLSession host '" + session.getPeerHost() + "'.");
                }
                return true;
            }
        };
        HttpsURLConnection.setDefaultHostnameVerifier(hv);
    }

2)编写以下方法,该方法在尝试连接到URL之前会调用doTrustToCertificates

    // connecting to URL
    public void connectToUrl(){
     doTrustToCertificates();//  
     URL url = new URL("https://www.example.com");
     HttpURLConnection conn = (HttpURLConnection)url.openConnection(); 
     System.out.println("ResponseCode ="+conn.getResponseCode());
   }

此呼叫将返回响应代码= 200表示连接成功。

有关更多详细信息和示例示例,请参考URL


0
投票

我相信您正在尝试使用SSL连接到某物,但某物所提供的证书未经root证书颁发机构(如verisign)验证。本质上,默认情况下,只有在试图连接某人的情况下,才能建立安全连接connect知道交易对手的密钥或诸如verisign之类的其他供应商可以介入,并说所提供的公钥确实是正确的。

ALL OS信任少数证书颁发机构,并且较小的证书颁发者需要由大型认证机构之一进行认证,如果您理解我的意思,那么该认证机构将组成一系列认证机构...

无论如何,现在回到了这一点。在编写Java小程序和Java服务器时,我遇到了类似的问题(希望有一天,我会写一篇完整的博文,介绍如何使所有安全性发挥作用:))]

[本质上,我要做的是从服务器中提取公共密钥,并将其存储在我的applet内的密钥库中,当我连接到服务器时,我使用此密钥库创建了一个信任工厂,并使用了该信任工厂来创建ssl连接。还有一些备用过程,例如将密钥添加到JVM的受信任主机,并在启动时修改默认信任库。

我大约两个月前做了这个,现在没有源代码。使用google,您应该可以解决此问题。如果您不能给我回信,并且我可以为您提供该项目的相关事件源代码,则不知道这是否可以解决您的问题,因为您没有提供导致这些异常的代码。此外,我正在使用applet进行工作,以为我看不到为什么它无法在Serverlets上运行...

P.S我无法在周末之前获取源代码,因为我的办公室已禁用外部SSH:(

SSLHandshakeException可以通过两种方法解决。

  1. 并入SSL

  • 获取SSL(通过询问源系统管理员,也可以由openssl命令下载,或任何浏览器下载证书)

  • 将证书添加到位于以下位置的信任库(证书)中JRE / lib / security

  • 在vm参数中提供信任库位置为“ -Djavax.net.ssl.trustStore =”

  • 忽略SSL

对于此#2,请在另一个stackoverflow网站上访问我的其他答案:How to ingore SSL verification Ignore SSL Certificate Errors with Java

现在我以这种方式解决了这个问题,

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.OutputStream;
// Create a trust manager that does not validate certificate chains like the 
default TrustManager[] trustAllCerts = new TrustManager[] {
    new X509TrustManager() {
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return null;
        }
        public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {
            //No need to implement. 
        }
        public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {
            //No need to implement. 
        }
    }
};
// Install the all-trusting trust manager
try {
    SSLContext sc = SSLContext.getInstance("SSL");
    sc.init(null, trustAllCerts, new java.security.SecureRandom());
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
    System.out.println(e);
}

0
投票

SSLHandshakeException可以通过两种方法解决。


-6
投票

现在我以这种方式解决了这个问题,


推荐问答