天天看點

解決javax.net.ssl.SSLHandshakeException:sun.security.validator.ValidatorException:PKIX路徑建構失敗錯誤? How to work-it in Tomcat 7 如何在Tomcat 7中工作

本文翻譯自: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);

// ...