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

这是最初的问题。

我得到这个错误:

详细消息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());

当前回答

在我的例子中,问题是web服务器只发送证书和中间CA,而不是根CA。 添加这个JVM选项解决了这个问题:- dcom .sun.security. enableaiacaissuer =true

支持权威信息访问扩展的caissuer访问方法是可用的。为了兼容性,它默认是禁用的,可以通过将系统属性com.sun.security. enableaiacaissuer设置为true来启用。 如果设置为true, Sun的CertPathBuilder的PKIX实现将使用证书的AIA扩展中的信息(除了指定的CertStores之外)来查找颁发的CA证书,前提是它是ldap、http或ftp类型的URI。

其他回答

我的cacerts文件完全是空的。我通过从我的windows机器(使用Oracle Java 7)复制cacerts文件并将其scp到我的Linux盒子(OpenJDK)来解决这个问题。

cd %JAVA_HOME%/jre/lib/security/
scp cacerts mylinuxmachin:/tmp

然后在Linux机器上

cp /tmp/cacerts /etc/ssl/certs/java/cacerts

到目前为止,它工作得很好。

在Linux下使用Tomcat 7,这就成功了。

String certificatesTrustStorePath = "/etc/alternatives/jre/lib/security/cacerts";
System.setProperty("javax.net.ssl.trustStore", certificatesTrustStorePath);
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");

在Linux下,$JAVA_HOME并不总是设置,但通常/etc/alternatives/jre指向$JAVA_HOME/jre

我想加入进来,因为我有一个QEMU环境,我必须在其中下载java文件。事实证明,QEMU中的/etc/ssl/certs/java/cacerts确实存在问题,因为它与主机环境中的/etc/ssl/certs/java/cacerts不匹配。主机环境位于公司代理的后面,因此java cacerts是一个定制版本。

如果您正在使用QEMU环境,请首先确保主机系统可以访问文件。例如,您可以先在您的主机上尝试此脚本。如果脚本在主机上运行得很好,但在QEMU上却不行,那么您也遇到了和我一样的问题。

为了解决这个问题,我必须对QEMU中的原始文件进行备份,将主机环境中的文件复制到QEMU chroot jail中,然后java才能在QEMU中正常下载文件。

更好的解决方案是将/etc挂载到QEMU环境中;但是我不确定其他文件是否会在这个过程中受到影响。所以我决定使用这个丑陋但简单的变通方法。

只是一个小hack。将“hudson.model.UpdateCenter.xml”文件中的URL从https更新为http

<?xml version='1.1' encoding='UTF-8'?>
<sites>
  <site>
    <id>default</id>
    <url>http://updates.jenkins.io/update-center.json</url>
  </site>
</sites>

必要时,您可以完全禁用SSL,或者每个连接禁用SSL(注意,这不建议用于生产环境!),参见https://stackoverflow.com/a/19542614/32453