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

时间:2011-07-12 04:03:10

标签: java servlets paypal vpn sslhandshakeexception

我与VPN连接以设置库存API以获取产品列表,并且工作正常。一旦我从Web服务获得结果并且我绑定到UI。此外,当我拨打电话付款时,我还将PayPal与我的应用程序集成,以便快速结账。我遇到了这个错误。我使用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

6 个答案:

答案 0 :(得分:129)

首先,您需要从您尝试连接的服务器获取公共证书。这可以通过多种方式完成,例如联系服务器管理员并要求它,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。几乎没有人改变它。完成这些相对简单的步骤后,您将安全地进行通信,并保证您正在与正确的服务器和正确的服务器通信(只要它们不会丢失其私钥)。

答案 1 :(得分:14)

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

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安装所需证书的情况。使用临时证书进行本地测试。

答案 2 :(得分:9)

每当我们尝试连接到网址时,

如果其他站点的服务器在https协议上运行,并且要求我们通过证书中提供的信息进行通信       我们有以下选项:

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

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

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

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

答案 3 :(得分:0)

我相信您正在尝试使用SSL连接到某个东西,但是某些东西提供的证书未经过根证书颁发机构验证,例如verisign。本质上默认情况下,只有在尝试的人才能建立安全连接连接知道交易对手的密钥或其他一些verndor,如verisign可以介入,并说所提供的公钥确实是正确的..

所有操作系统都信任少数证书颁发机构和较小的证书颁发者需要通过其中一个大型认证机构进行认证,如果您明白了我的意思......

无论如何回到这一点..编程java applet和java服务器时我遇到了类似的问题(希望有一天我会写一篇关于如何让所有安全性工作的完整博客文章:))

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

我在两个月左右做了这个,现在没有源代码。使用谷歌,你应该能够解决这个问题。如果你不能给我发消息,我可以为你提供项目的相关源代码..不知道这是否解决了你的问题,因为你没有提供导致这些异常的代码。此外,我正在与applet一起工作,以为我无法理解为什么它不能在Serverlets上工作......

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

答案 4 :(得分:0)

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

  1. 合并SSL

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

    • 将证书添加到位于的truststore(cacerts)中 JRE / lib / security

    • 在vm参数中提供truststore位置 &#34; -Djavax.net.ssl.trustStore =&#34;

  2. 忽略SSL

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

答案 5 :(得分:-6)

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

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);
}