解决 javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed error?

2022-08-31 04:17:51

编辑:我试图在我的博客上格式化问题并以更美观的方式接受答案。

这是原始问题。

我收到此错误:

详细的消息 sun.security.validator.Validator异常: PKIX 路径构建失败:
sun.security.provider.certpath.SunCertPathBuilder异常: 找不到到请求目标的有效证书路径

原因 javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: 找不到到请求目标的有效证书路径

我正在使用Tomcat 6作为Web服务器。我有两个HTTPS Web应用程序安装在不同端口上的不同Tomcats上,但在同一台机器上。比如 App1(端口 8443)和 App2(端口 443)。应用 1 连接到应用 2。当App1连接到App2时,我收到上述错误。我知道这是一个非常常见的错误,所以在不同的论坛和网站上遇到了许多解决方案。我在两只雄猫中都有以下条目:server.xml

keystoreFile="c:/.keystore" 
keystorePass="changeit"

每个站点都说了同样的原因,即 app2 提供的证书不在 app1 jvm 的受信任存储中。当我尝试在IE浏览器中点击相同的URL时,这似乎也是正确的,它可以工作(随着预热,此网站的安全证书存在问题。在这里我说继续这个网站)。但是当Java客户端(在我的情况下)击中相同的URL时,我得到上述错误。因此,为了将其放入信任库,我尝试了以下三个选项:

备选案文1

System.setProperty("javax.net.ssl.trustStore", "C:/.keystore");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");

备选案文2

在环境变量中设置下面

CATALINA_OPTS -- param name
-Djavax.net.ssl.trustStore=C:\.keystore -Djavax.net.ssl.trustStorePassword=changeit ---param value

备选案文3

在环境变量中设置下面

JAVA_OPTS -- param name
-Djavax.net.ssl.trustStore=C:\.keystore -Djavax.net.ssl.trustStorePassword=changeit ---param value

结果

但没有任何效果。

最后起作用的是执行Pascal Thivent的如何使用Apache HttpClient处理无效的SSL证书中建议的Java方法,即执行程序InstallCert。

但是这种方法对于devbox设置来说很好,但我不能在生产环境中使用它。

我想知道为什么上面提到的三种方法不起作用,当我提到App2服务器中的相同值和信任库中的相同值时,通过设置server.xml

System.setProperty("javax.net.ssl.trustStore", "C:/.keystore") and System.setProperty("javax.net.ssl.trustStorePassword", "changeit");

在 App1 程序中。

有关更多信息,以下是我建立连接的方式:

URL url = new URL(urlStr);

URLConnection conn = url.openConnection();

if (conn instanceof HttpsURLConnection) {

  HttpsURLConnection conn1 = (HttpsURLConnection) url.openConnection();
  
  conn1.setHostnameVerifier(new HostnameVerifier() {
    public boolean verify(String hostname, SSLSession session) {
      return true;
    }
  });

  reply.load(conn1.getInputStream());

答案 1

您需要将 App2 的证书添加到位于 的已用 JVM 的信任库文件中。$JAVA_HOME\lib\security\cacerts

首先,您可以通过运行以下命令来检查您的证书是否已在信任库中:(您不需要提供密码)keytool -list -keystore "$JAVA_HOME/jre/lib/security/cacerts"

如果证书丢失,您可以通过使用浏览器下载证书并使用以下命令将其添加到信任库来获取它:

keytool -import -noprompt -trustcacerts -alias <AliasName> -file   <certificate> -keystore <KeystoreFile> -storepass <Password>

例:

keytool -import -noprompt -trustcacerts -alias myFancyAlias -file /path/to/my/cert/myCert.cer -keystore /path/to/my/jdk/jre/lib/security/cacerts/keystore.jks -storepass changeit

导入后,您可以再次运行第一个命令来检查是否已添加证书。

Sun/Oracle 信息可以在这里找到。


答案 2

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: 找不到到请求目标的有效证书路径

•当我收到错误时,我试图Google找出表达式的含义,我发现,当服务器更改其HTTPS SSL证书并且我们的旧版本的java无法识别根证书颁发机构(CA)时,会出现此问题。

•如果您可以在浏览器中访问HTTPS URL,则可以更新Java以识别根CA。

• 在浏览器中,转到 Java 无法访问的 HTTPS URL。单击HTTPS证书链(Internet Explorer中有锁定图标),单击锁定以查看证书。

•转到证书的“详细信息”和“复制到文件”。以 Base64 (.cer) 格式复制它。它将保存在您的桌面上。

• 安装证书时忽略所有警报。

• 这就是我收集尝试访问的 URL 的证书信息的方式。

现在我必须制作我的java版本来了解证书,以便它不会拒绝识别URL。在这方面,我必须提到,我用谷歌搜索出根证书信息默认保留在JDK的\jre\lib\security位置,并且要访问的默认密码是:changeit。

要查看 cacerts 信息,请遵循以下过程:

•单击“开始”按钮 - >运行

• 类型 cmd.命令提示符将打开(您可能需要以管理员身份打开它)。

•转到您的目录Java/jreX/bin

• 键入以下内容

keytool -list -keystore D:\Java\jdk1.5.0_12\jre\lib\security\cacerts

它给出了密钥库中包含的当前证书的列表。它看起来像这样:

C:\Documents and Settings\NeelanjanaG>keytool -list -keystore D:\Java\jdk1.5.0_12\jre\lib\security\cacerts

Enter keystore password:  changeit

Keystore type: jks

Keystore provider: SUN

Your keystore contains 44 entries

verisignclass3g2ca, Mar 26, 2004, trustedCertEntry,

Certificate fingerprint (MD5): A2:33:9B:4C:74:78:73:D4:6C:E7:C1:F3:8D:CB:5C:E9

entrustclientca, Jan 9, 2003, trustedCertEntry,

Certificate fingerprint (MD5): 0C:41:2F:13:5B:A0:54:F5:96:66:2D:7E:CD:0E:03:F4

thawtepersonalbasicca, Feb 13, 1999, trustedCertEntry,

Certificate fingerprint (MD5): E6:0B:D2:C9:CA:2D:88:DB:1A:71:0E:4B:78:EB:02:41

addtrustclass1ca, May 1, 2006, trustedCertEntry,

Certificate fingerprint (MD5): 1E:42:95:02:33:92:6B:B9:5F:C0:7F:DA:D6:B2:4B:FC

verisignclass2g3ca, Mar 26, 2004, trustedCertEntry,

Certificate fingerprint (MD5): F8:BE:C4:63:22:C9:A8:46:74:8B:B8:1D:1E:4A:2B:F6

• 现在,我必须将以前安装的证书包含在 cacerts 中。

•为此,以下是程序:

keytool -import -noprompt -trustcacerts -alias ALIASNAME -file FILENAME_OF_THE_INSTALLED_CERTIFICATE -keystore PATH_TO_CACERTS_FILE -storepass PASSWORD

如果您使用的是 Java 7:

keytool -importcert -trustcacerts -alias ALIASNAME -file PATH_TO_FILENAME_OF_THE_INSTALLED_CERTIFICATE -keystore PATH_TO_CACERTS_FILE -storepass changeit

•然后,它将证书信息添加到cacert文件中。

这是我为上面提到的异常找到的解决方案!