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

这是最初的问题。

我得到这个错误:

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

当前回答

对于运行在Ubuntu服务器上的Tomcat,使用"ps -ef | grep Tomcat "命令查看正在使用的Java:

示例:

/home/mcp01$ **ps -ef |grep tomcat**
tomcat7  28477     1  0 10:59 ?        00:00:18 **/usr/local/java/jdk1.7.0_15/bin/java** -Djava.util.logging.config.file=/var/lib/tomcat7/conf/logging.properties -Djava.awt.headless=true -Xmx512m -XX:+UseConcMarkSweepGC -Djava.net.preferIPv4Stack=true -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs=/usr/share/tomcat7/endorsed -classpath /usr/share/tomcat7/bin/bootstrap.jar:/usr/share/tomcat7/bin/tomcat-juli.jar -Dcatalina.base=/var/lib/tomcat7 -Dcatalina.home=/usr/share/tomcat7 -Djava.io.tmpdir=/tmp/tomcat7-tomcat7-tmp org.apache.catalina.startup.Bootstrap start
1005     28567 28131  0 11:34 pts/1    00:00:00 grep --color=auto tomcat

然后进入:cd /usr/local/java/jdk1.7.0_15/jre/lib/security

默认的cacerts文件位于这里。将不受信任的证书插入其中。

其他回答

如何在Tomcat 7中工作

我想在Tomcat应用程序中支持自签名证书,但下面的代码片段无法工作

import java.io.DataOutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class HTTPSPlayground {
    public static void main(String[] args) throws Exception {

        URL url = new URL("https:// ... .com");
        HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();

        httpURLConnection.setRequestMethod("POST");
        httpURLConnection.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
        httpURLConnection.setDoOutput(true);
        DataOutputStream wr = new DataOutputStream(httpURLConnection.getOutputStream());

        String serializedMessage = "{}";
        wr.writeBytes(serializedMessage);
        wr.flush();
        wr.close();

        int responseCode = httpURLConnection.getResponseCode();
        System.out.println(responseCode);
    }
}

这就是解决我问题的方法:

1)下载。crt文件

echo -n | openssl s_client -connect <your domain>:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > ~/<your domain>.crt

将<您的域名>替换为您的域名(例如jossef.com)

2)在Java的cacerts证书存储中应用.crt文件

keytool -import -v -trustcacerts -alias <your domain> -file ~/<your domain>.crt -keystore <JAVA HOME>/jre/lib/security/cacerts -keypass changeit -storepass changeit

将<您的域名>替换为您的域名(例如jossef.com) 将<JAVA HOME>替换为JAVA主目录

3)破解它

尽管iv在Java的默认证书存储中安装了我的证书,但Tomcat忽略了这一点(似乎它没有配置为使用Java的默认证书存储)。

要破解这个问题,在代码中添加以下代码:

String certificatesTrustStorePath = "<JAVA HOME>/jre/lib/security/cacerts";
System.setProperty("javax.net.ssl.trustStore", certificatesTrustStorePath);

// ...

在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

我有这个问题与Android工作室当我背后的代理。我使用的是Crashlytics,它试图在构建过程中上传映射文件。

我将丢失的代理证书添加到位于 /用户/【用户名】/文件/ Android Studio.app / jdk / jre /内容/内容/ Home / jre / lib / security /除

keytool -import -trustcacerts -keystore cacerts -storepass [password] -noprompt -alias [alias] -file [my_certificate_location]

例如,使用默认信任库密码 keytool -import -trustcacerts -keystore cacerts -storepass changeit -noprompt -alias myproxycert -file /Users/myname/Downloads/MyProxy.crt

可部署解决方案(Alpine Linux)

为了能够在我们的应用程序环境中修复这个问题,我们准备了如下的Linux终端命令:

cd ~

将在主目录中生成证书文件。

apk add openssl

该命令在alpine Linux中安装openssl。您可以找到其他Linux发行版的适当命令。

openssl s_client -connect <host-dns-ssl-belongs> < /dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > public.crt

生成所需的证书文件。

sudo $JAVA_HOME/bin/keytool -import -alias server_name -keystore $JAVA_HOME/lib/security/cacerts -file public.crt -storepass changeit -noprompt

使用'keytool'程序将生成的文件应用到JRE。

注意:请将您的DNS替换为<host- DNS -ssl-belong >

注意:请注意-noprompt不会提示验证信息(yes/no), -storepass changeit参数将禁用密码提示并提供所需的密码(默认为'changeit')。这两个属性将允许您在应用程序环境中使用这些脚本,例如构建Docker映像。

注3:如果你是通过Docker部署你的应用程序,你可以生成一次秘密文件,并把它放在你的应用程序项目文件中。您不需要一次又一次地生成它。

对我来说,这个错误也出现在试图连接到一个NGINX反向代理背后的进程,它正在处理SSL。

事实证明,问题在于一个没有连接整个证书链的证书。 当我添加中间证书时,问题就解决了。

希望这能有所帮助。