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

新手上路,请多包涵

我连接到 VPN 以设置库存 API 以获取产品列表并且它工作正常。一旦我从网络服务获得结果,我就绑定到 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

原文由 selladurai 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.1k
2 个回答

首先,您需要从您尝试连接的服务器获取公共证书。这可以通过多种方式完成,例如联系服务器管理员并请求它, 使用 OpenSSL 下载它,或者,因为这似乎是一个 HTTP 服务器,使用任何浏览器连接到它,查看页面的安全信息,并保存证书的副本。 (谷歌应该能够准确地告诉你为你的特定浏览器做什么。)

现在您已将证书保存在文件中,您需要将其添加到 JVM 的信任库中。在 $JAVA_HOME/jre/lib/security/ 对于 JRE 或 $JAVA_HOME/lib/security 对于 JDK,有一个名为 cacerts 的文件要导入新证书,请以有权写入 cacerts 的用户身份运行 keytool:

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

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

原文由 Ryan Stewart 发布,翻译遵循 CC BY-SA 4.0 许可协议

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

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

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

  1. 在正常的业务案例中,我们可能会连接到组织中的内部 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);
    }

  1. 编写下面的方法,在尝试连接到 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

原文由 Shirishkumar Bari 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题