java - unable - sun.security.validator.validatorexception: pkix path building failed




解決javax.net.ssl.SSLHandshakeException:sun.security.validator.ValidatorException:PKIX路徑構建失敗錯誤? (8)

編輯: -試圖格式化問題,並在我的Blog接受更多的方式接受答案

這是原始問題: -

我收到這個錯誤

詳細消息sun.security.validator.ValidatorException:PKIX路徑構建失敗:
sun.security.provider.certpath.SunCertPathBuilderException:無法找到要求的目標的有效證書路徑

導致javax.net.ssl.SSLHandshakeException:sun.security.validator.ValidatorException:PKIX路徑構建失敗:sun.security.provider.certpath.SunCertPathBuilderException:無法找到要求的目標的有效證書路徑

我使用tomcat 6作為網絡服務器。 我有兩個https webbapplication安裝在differte端口上的不同tomcat上,但在同一台機器上。 說App1(port 8443)App2(port 443)App1連接到App2 。當App1連接到App2 i以上錯誤。 我知道這是非常常見的錯誤,因此在不同論壇和網站上發布了許多解決方案。 我有兩個tomcat即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");

Option2在環境變量中設置如下

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

Option3在環境變量中設置如下

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

但沒有任何工作

最後的工作是執行如何使用Apache HttpClient處理無效SSL證書中所建議的java方法 由Pascal Thivent執行,即執行程序InstallCert。

但是這種方法適用於devbox安裝,但我無法在生產環境中使用它。

我想知道為什麼上面提到的三種方法不起作用,當我在app2服務器的server.xml中提到了相同的值並且通過設置在信任庫中提供了相同的值時

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

javax.net.ssl.SSLHandshakeException:sun.security.validator.ValidatorException:PKIX路徑構建失敗:sun.security.provider.certpath.SunCertPathBuilderException:無法找到要求的目標的有效證書路徑

•當我收到錯誤信息時,我嘗試Google表達該表達式的含義,並且發現,當服務器更改其HTTPS SSL證書時,會發生此問題,並且我們的舊版本的Java不能識別根證書頒發機構(CA) 。

•如果您可以在瀏覽器中訪問HTTPS URL,則可以更新Java以識別根CA.

•在瀏覽器中,轉至Java無法訪問的HTTPS URL。 點擊HTTPS證書鏈(Internet Explorer中有鎖圖標),點擊鎖來查看證書。

•轉到證書的“詳細信息”和“複製到文件”。 以Base64(.cer)格式複制它。 它將保存在桌面上。

•安裝證書,忽略所有警報。

這是我收集我嘗試訪問的URL的證書信息的方式。

現在我不得不讓我的Java版本了解證書,以便進一步它不拒絕識別URL。 在這方面,我必須提及我發現JDK的\ jre \ lib \ security位置默認存在根證書信息,並且訪問的默認密碼是: changeit。

要查看cacerts信息,請遵循以下步驟:

•點擊開始按鈕 - >運行

•輸入cmd。 命令提示符打開(您可能需要以管理員身份打開它)。

轉到Java/jreX/bin目錄

•輸入以下內容

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

輸入密鑰庫密碼:changeit

密鑰庫類型:jks

密鑰庫提供商:SUN

您的密鑰庫包含44個條目

verisignclass3g2ca,2004年3月26日,trustedCertEntry,

證書指紋(MD5):A2:33:9B:4C:74:78:73:D4:6C:E7:C1:F3:8D:CB:5C:E9

entrustclientca,2003年1月9日,trustedCertEntry,

證書指紋(MD5):0C:41:2F:13:5B:A0:54:F5:96:66:2D:7E:CD:0E:03:F4

thawtepersonalbasicca,1999年2月13日,trustedCertEntry,

證書指紋(MD5):E6:0B:D2:C9:CA:2D:88:DB:1A:71:0E:4B:78:EB:02:41

addtrustclass1ca,2006年5月1日,trustedCertEntry,

證書指紋(MD5):1E:42:95:02:33:92:6B:B9:5F:C0:7F:DA:D6:B2:4B:FC

verisignclass2g3ca,2004年3月26日,trustedCertEntry,

證書指紋(MD5):F8:BE:C4:63:22:C9:A8:46:74:8B:B8:1D:1E:4A:2B:F6

•現在我必須將之前安裝的證書包含在cacerts中。

•為此,程序如下:

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

如果您正在使用Java 7:

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

然後它會將證書信息添加到cacert文件中。

這是我為上述Exception提供的解決方案!


如何在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
  • <your domain>替換<your domain> (例如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
  • <your domain>替換<your domain> (例如jossef.com
  • 用你的java主目錄替換<JAVA HOME>

3)破解它

即使iv'e在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



對於在Ubuntu服務器上運行的Tomcat,要找出正在使用哪個Java,請使用“ps -ef | grep tomcat”命令:

樣品:

/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文件位於這裡。 將不可信證書插入它。


您需要將App2的證書添加到位於%JAVA_HOME%\lib\security\cacerts的已用JVM的信任庫文件。

首先,您可以通過運行以下命令來檢查您的證書是否已經在truststore中: keytool -list -keystore "%JAVA_HOME%/jre/lib/security/cacerts" (您不需要提供密碼)

如果您的證書丟失,您可以通過使用瀏覽器下載證書並使用以下命令將其添加到信任庫來獲取證書:

keytool -import -noprompt -trustcacerts -alias <AliasName> -file <certificate> -keystore <KeystoreFile> -storepass <Password>

導入後,您可以再次運行第一個命令以檢查您的證書是否已添加。

Sun / Oracle信息可以在here找到。


我寫了一個小型的win32(WinXP 32bit testet)stupid cmd(commandline)腳本,它在程序文件中查找所有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

我的cacerts文件完全是空的。 我通過從我的Windows機器上複製cacerts文件(即使用Oracle Java 7)並將其解密到我的Linux機器(OpenJDK)來解決此問題。

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

然後在linux機器上

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

迄今為止效果很好。