解决javax.net.ssl.SSLHandshakeException:sun.security.validator.ValidatorException:PKIX路径构建失败错误?

本文介绍了如何解决在使用Tomcat 6时遇到的javax.net.ssl.SSLHandshakeException,该错误通常是由于证书不被Java信任造成的。作者尝试了多种方法,包括更新Java版本、手动添加证书到信任存储,但最终成功的方法是在Java环境中使用InstallCert程序。然而,这种方法不适合生产环境。文章提供了详细的错误信息和解决步骤。
摘要由CSDN通过智能技术生成

本文翻译自:Resolving javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed Error?

Edit :- Tried to format the question and accepted answer in more presentable way at mine Blog 编辑:-试图在我的博客上以更恰当的方式设置问题和接受的答案的格式

Here is the original issue. 这是原始问题。

I am getting this error: 我收到此错误:

detailed message sun.security.validator.ValidatorException: PKIX path building failed: 详细消息sun.security.validator.ValidatorException:PKIX路径构建失败:
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target sun.security.provider.certpath.SunCertPathBuilderException:无法找到到请求目标的有效证书路径

cause 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 导致javax.net.ssl.SSLHandshakeException:sun.security.validator.ValidatorException:PKIX路径构建失败:sun.security.provider.certpath.SunCertPathBuilderException:找不到指向所请求目标的有效证书路径

I am using Tomcat 6 as webserver. 我正在使用Tomcat 6作为Web服务器。 I have two HTTPS web applications installed on different Tomcats on different ports but on the same machine. 我有两个HTTPS Web应用程序安装在不同端口上但在同一台机器上的不同Tomcat上。 Say App1(port 8443) and App2(port 443) . 说出App1(port 8443)App2(port 443) App1 connects to App2 . App1连接到App2 When App1 connects to App2 I get the above error. App1连接到App2 ,出现上述错误。 I know this is a very common error so came across many solutions on different forums and sites. 我知道这是一个非常常见的错误,因此在不同的论坛和站点上遇到了许多解决方案。 I have the below entry in server.xml of both Tomcats: 我在两个Tomcat的server.xml中都有以下条目:

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

Every site says the same reason that certificate given by app2 is not in the trusted store of app1 jvm. 每个站点都表示由app2颁发的证书不在app1 jvm的受信任存储区中的相同原因。 This seems to be true also when I tried to hit the same URL in IE browser, it works (with warming, There is a problem with this web site's security certificate. Here I say continue to this website). 当我尝试在IE浏览器中命中相同的URL时,这似乎也是正确的(正常运行,此网站的安全证书有问题。在这里我说继续浏览此网站)。 But when same URL is hit by Java client (in my case) I get the above error. 但是,当Java客户端(在我的情况下)击中相同的URL时,会出现上述错误。 So to put it in the truststore I tried these three options: 因此,将其放入信任库中,我尝试了以下三个选项:

Option1 选项1

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

Option2 Setting below in environment variable Option2在环境变量中进行以下设置

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

Option3 Setting below in environment variable Option3在环境变量中进行以下设置

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

But nothing worked . 但是没有任何效果

What at last worked is executing the Java approach suggested in How to handle invalid SSL certificates with Apache HttpClient? 最后执行的工作是执行如何使用Apache HttpClient处理无效的SSL证书中建议的Java方法 by Pascal Thivent ie executing the program InstallCert. 由Pascal Thivent编写,即执行程序InstallCert。

But this approach is fine for devbox setup but I can not use it at production environment. 但是这种方法对于devbox设置来说很好,但是我不能在生产环境中使用它。

I am wondering why three approaches mentioned above did not work when I have mentioned the same values in server.xml of app2 server and same values in truststore by setting 我想知道为什么我通过设置app2 server.xml的相同值和truststore中的相同值时上述三种方法不起作用

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

in app1 program. app1程序中。

For more information this is how I am making the connection: 有关更多信息,这是我进行连接的方式:

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楼

参考:https://stackoom.com/question/eMLe/解决javax-net-ssl-SSLHandshakeException-sun-security-validator-ValidatorException-PKIX路径构建失败错误


#2楼

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 javax.net.ssl.SSLHandshakeException:sun.security.validator.ValidatorException:PKIX路径构建失败:sun.security.provider.certpath.SunCertPathBuilderException:找不到指向所请求目标的有效证书路径

• When I got the error, I tried to Google out the meaning of the expression and I found, this issue occurs when a server changes their HTTPS SSL certificate, and our older version of java doesn't recognize the root certificate authority (CA). •收到错误消息后,我尝试用Google搜索表达式的含义,然后发现,当服务器更改其HTTPS SSL证书并且我们的Java较旧版本无法识别根证书颁发机构(CA)时,就会发生此问题。 。

• If you can access the HTTPS URL in your browser then it is possible to update Java to recognize the root CA. •如果您可以在浏览器中访问HTTPS URL,则可以更新Java以识别根CA。

• In your browser, go to the HTTPS URL that Java could not access. •在浏览器中,转到Java无法访问的HTTPS URL。 Click on the HTTPS certificate chain (there is lock icon in the Internet Explorer), click on the lock to view the certificate. 单击HTTPS证书链(Internet Explorer中有锁图标),然后单击锁以查看证书。

• Go to “Details” of the certificate and “Copy to file”. •转到证书的“详细信息”和“复制到文件”。 Copy it in Base64 (.cer) format. 将其复制为Base64(.cer)格式。 It will be saved on your Desktop. 它将保存在您的桌面上。

• Install the certificate ignoring all the alerts. •安装证书时忽略所有警报。

• This is how I gathered the certificate information of the URL that I was trying to access. •这就是我收集尝试访问的URL的证书信息的方式。

Now I had to make my java version to know about the certificate so that further it doesn't refuse to recognize the URL. 现在,我必须使自己的Java版本知道该证书,以便它不会拒绝识别URL。 In this respect I must mention that I googled out that root certificate information stays by default in JDK's \\jre\\lib\\security location, and the default password to access is: changeit. 在这方面,我必须提到,我已根除根证书信息,默认情况下将其保留在JDK的\\ jre \\ lib \\ security位置,并且访问的默认密码为: changeit。

To view the cacerts information the following are the procedures to follow: 要查看证书信息,请遵循以下步骤:

• Click on Start Button-->Run •单击开始按钮->运行

• Type cmd. •键入cmd。 The command prompt opens (you may need to open it as administrator). 将打开命令提示符(您可能需要以管理员身份打开它)。

• Go to your Java/jreX/bin directory •转到您的Java/jreX/bin目录

• Type the following •输入以下内容

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

It gives the list of the current certificates contained within the keystore. 它给出了密钥库中包含的当前证书的列表。 It looks something like this: 看起来像这样:

C:\\Documents and Settings\\NeelanjanaG>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 输入密钥库密码:changeit

Keystore type: jks 密钥库类型:jks

Keystore provider: SUN 密钥库提供者:SUN

Your keystore contains 44 entries 您的密钥库包含44个条目

verisignclass3g2ca, Mar 26, 2004, trustedCertEntry, verisignclass3g2ca,2004年3月26日,trustedCertEntry,

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

entrustclientca, Jan 9, 2003, trustedCertEntry, entrustclientca,2003年1月9日,trustedCertEntry,

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

thawtepersonalbasicca, Feb 13, 1999, trustedCertEntry, thawtepersonalbasicca,1999年2月13日,trustedCertEntry,

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

addtrustclass1ca, May 1, 2006, trustedCertEntry, addtrustclass1ca,2006年5月1日,trustedCertEntry,

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

verisignclass2g3ca, Mar 26, 2004, trustedCertEntry, verisignclass2g3ca,2004年3月26日,trustedCertEntry,

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

• Now I had to include the previously installed certificate into the cacerts. •现在,我必须将以前安装的证书包含在cacerts中。

• For this the following is the procedure: •为此,请执行以下步骤:

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

If you are using Java 7: 如果您使用的是Java 7:

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

• It will then add the certificate information into the cacert file. •然后它将证书信息添加到cacert文件中。

It is the solution I found for the Exception mentioned above!! 这是我为上述异常找到的解决方案!


#3楼

i wrote a small win32 (WinXP 32bit testet) stupid cmd (commandline) script which looks for all java versions in program files and adds a cert to them. 我写了一个小的win32(WinXP 32bit testet)愚蠢的cmd(命令行)脚本,该脚本在程序文件中查找所有Java版本并向它们添加证书。 The Password needs to be the default "changeit" or change it yourself in the script :-) 密码必须是默认的“ 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

#4楼

My cacerts file was totally empty. 我的cacerts文件是完全空的。 I solved this by copying the cacerts file off my windows machine (that's using Oracle Java 7) and scp'd it to my Linux box (OpenJDK). 我通过从Windows计算机(使用Oracle Java 7)复制cacerts文件并将其scp'd到我的Linux机器(OpenJDK)中来解决此问题。

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

and then on the linux machine 然后在linux机器上

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

It's worked great so far. 到目前为止效果很好。


#5楼

For Tomcat running on Ubuntu server, to find out which Java is being used, use "ps -ef | grep tomcat" command: 对于在Ubuntu服务器上运行的Tomcat,要找出正在使用的Java,请使用“ ps -ef | grep tomcat”命令:

Sample: 样品:

/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

Then, we can go in to: cd /usr/local/java/jdk1.7.0_15/jre/lib/security 然后,我们可以进入: cd /usr/local/java/jdk1.7.0_15/jre/lib/security

Default cacerts file is located in here. 默认的cacerts文件位于此处。 Insert the untrusted certificate into it. 将不受信任的证书插入其中。


#6楼

How to work-it in Tomcat 7 如何在Tomcat 7中工作

I wanted to support a self signed certificate in a Tomcat App but the following snippet failed to work 我想在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);
    }
}

this is what solved my issue: 这是解决我的问题的方法:

1) Download the .crt file 1)下载.crt文件

echo -n | openssl s_client -connect <your domain>:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > ~/<your domain>.crt
  • replace <your domain> with your domain (eg jossef.com ) <your domain>替换为您的域(例如jossef.com

2) Apply the .crt file in Java's cacerts certificate store 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
  • replace <your domain> with your domain (eg jossef.com ) <your domain>替换为您的域(例如jossef.com
  • replace <JAVA HOME> with your java home directory 用Java主目录替换<JAVA HOME>

3) Hack it 3)破解

Even though iv'e installed my certificate in Java 's default certificate stores, Tomcat ignores that (seems like it's not configured to use Java's default certificate stores). 即使我在Java的默认证书存储区中安装了我的证书, Tomcat仍然忽略了这一点 (似乎未将其配置为使用Java的默认证书存储区)。

To hack this, add the following somewhere in your code: 要对此进行破解,请在代码中的以下位置添加以下内容:

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

// ...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值