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

这是最初的问题。

我得到这个错误:

详细消息sun.security.validator.ValidatorException: PKIX路径 构建失败: provider.certpath. suncertpathbuilderexception:不能 找到请求目标的有效认证路径 导致javax.net.ssl.SSLHandshakeException: validatorexception: PKIX路径构建 失败:sun.security.provider.certpath.SunCertPathBuilderException: 无法找到请求目标的有效认证路径

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

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

每个站点都说明了app2给出的证书不在app1 jvm的可信存储区中的相同原因。这似乎也是真的,当我试图在IE浏览器中点击相同的URL,它工作(与升温,有一个问题与此网站的安全证书。在这里我说继续这个网站)。但是当相同的URL被Java客户端(在我的情况下)击中时,我得到上述错误。为了把它放到信任库中,我尝试了以下三个选项:

选项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

结果

但是什么都不管用。

最后工作是执行Java方法建议如何处理无效的SSL证书与Apache HttpClient?通过Pascal Thivent,即执行程序InstallCert。

但这种方法适用于开发盒设置,但我不能在生产环境中使用它。

我想知道为什么上面提到的三种方法都不工作,而我已经通过设置在App2服务器的server.xml中提到了相同的值,在truststore中也提到了相同的值

System.setProperty("javax.net.ssl.trustStore", "C:/.keystore")和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());

当前回答

我写了一个小的win32 (WinXP 32位测试)愚蠢的cmd(命令行)脚本,它在程序文件中查找所有java版本,并向它们添加一个证书。 密码必须是默认的“changeit”,或者在脚本中自己修改:-)

@echo off

for /F  %%d in ('dir /B %ProgramFiles%\java') do (
    %ProgramFiles%\Java\%%d\bin\keytool.exe -import -noprompt -trustcacerts -file some-exported-cert-saved-as.crt -keystore %ProgramFiles%\Java\%%d\lib\security\cacerts -storepass changeit
)

pause

其他回答

查看各种证书内容和通过标准openssl过程生成的证书,我注意到openssl根证书的AutorityKeyIdentifier被设置为本身。也许有一种方法可以克服它……但我不知道……

然后我用Java11和BouncyCastle开发了一个小应用程序来生成根证书和密钥,现在在github上:https://github.com/kendarorg/JavaCaCertGenerator

使用该工具生成的根证书不包含AuthorityKeyIdentifier,可以使用keytool直接安装在cacert存储区上。当我创建然后csr和ext文件的域名,这将验证对cacert存储包含根..再也没有握手异常了!

可能是cacert不允许递归AuthorityKeyIdentifier?我不知道,但我会欣赏一些评论:)

另一个原因可能是JDK的过时版本。我使用的jdk版本为1.8.0_60,只需更新到最新版本就解决了证书问题。

对于MacOS X,下面是我必须在'importcert'选项中尝试双连字符的确切命令,这是有效的:

sudo keytool -–importcert -file /PathTo/YourCertFileDownloadedFromBrowserLockIcon.crt -keystore /Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/lib/security/cacerts -alias "Cert" -storepass changeit

关注@NDeveloper的精彩答案。当然,我做了复制粘贴,改变了值,我得到

Illegal option:  ?import

我确实签出了连字符,我看到答案是使用ASCII的连字符

– 8211

如果你遇到问题,检查ASCII码,为我做的伎俩是这个代码= 45

- 45

我的代码

keytool -import -noprompt -trustcacerts -alias Certificado -file "C:\Users\JavIut\Desktop\Company\Certificados\Certificado.cer" -keystore "C:\Program Files\Java\jdk1.8.0_121\jre\lib\security\cacerts"

对我来说,这篇文章中公认的解决方案并不奏效:https://stackoverflow.com/a/9619478/4507034。

相反,我设法通过将认证导入到我的机器信任的认证来解决这个问题。

步骤:

转到URL(例如。https://localhost:8443/yourpath),其中认证不起作用。 导出上述帖子中描述的认证。 在windows机器上打开:管理计算机证书 进入受信任的根证书颁发机构->证书 在这里导入您的your_certification_name。cer文件。