首页 文章

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

提问于
浏览
79

我与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

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

  • 121

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

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

  • 13

    每当我们尝试连接到URL时,

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

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

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

    for the point no 2 we have to follow below steps :

    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 .

  • 9

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

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

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

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

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

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

  • -5

    SSLHandshakeException可以通过2种方式解决 .

    • 合并SSL

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

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

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

    • 忽略SSL

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

  • 0

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

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

相关问题