1. ホーム

[解決済み] [Solved] javax.net.ssl.SSLHandshakeException の解決: sun.security.validator.ValidatorException: PKIX パスの構築に失敗しました エラー?

2022-04-17 16:49:12

質問

編集する : 質問と回答をより見やすくするために、私の ブログ .

以下は、元の問題です。

このエラーが発生します。

詳細メッセージ sun.security.validator.ValidatorException: PKIX パス のビルドに失敗しました。

sun.security.provider.certpath.SunCertPathBuilderException: unable to 要求されたターゲットへの有効な証明書パスが見つかりました。

javax.net.ssl.SSLHandshakeException を発生させます。 sun.security.validator.ValidatorException: PKIX パスの構築 failed: sun.security.provider.certpath.SunCertPathBuilderException: 要求されたターゲットに対する有効な認証パスを見つけることができません

私は、WebサーバーとしてTomcat 6を使用しています。私は、2つのHTTPSウェブアプリケーションを、同じマシン上の異なるTomcatに異なるポートでインストールしています。App1 (ポート 8443) と App2 (ポート 443) とします。App1 は App2 に接続します。App1 が App2 に接続すると、上記のエラーが表示されます。私はこれが非常に一般的なエラーであることを知っているので、異なるフォーラムやサイトで多くの解決策に出会いました。私は以下のエントリを server.xml の両方のTomcatsの

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

どのサイトも同じ理由で、app2が与えた証明書がapp1 jvmの信頼できるストアにない、と言っています。これは、IEブラウザで同じURLを叩いてみても同じようで、動作します(There is a problem with this web site's security certificate.と暖かく表示されます)。ここでは、このWebサイトに続けると言っています)。しかし、同じURLをJavaクライアントで叩くと(私の場合)、上記のエラーが発生する。そこで、トラストストアに入れるために、以下の3つのオプションを試してみました。

オプション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のアプローチを実行することです。 Apache HttpClientで無効なSSL証明書を処理する方法は? Pascal Thivent氏によって、InstallCertというプログラムが実行されています。

しかし、この方法はdevboxのセットアップには良いのですが、本番環境では使えません。

で同じ値を指定しているのに、なぜ上記の3つのアプローチがうまくいかないのか不思議です。 server.xml を設定することで、App2サーバーのトラストストアに同じ値を設定することができます。

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());

解決方法は?

の証明書を追加する必要があります。 アプリ2 を使用するトラストストア・ファイルに追加します。 JVM にある $JAVA_HOME\lib\security\cacerts .

まず、以下のコマンドを実行することで、証明書がすでにトラストストアに登録されているかどうかを確認します。 keytool -list -keystore "$JAVA_HOME/jre/lib/security/cacerts" (パスワードは必要ありません)

証明書がない場合は、ブラウザでダウンロードし、以下のコマンドでトラストストアに追加することで取得することができます。

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

keytool -import -noprompt -trustcacerts -alias myFancyAlias -file /path/to/my/cert/myCert.cer -keystore /path/to/my/jdk/jre/lib/security/cacerts/keystore.jks -storepass changeit

インポート後、最初のコマンドを再度実行して、証明書が追加されたかどうかを確認することができます。

Sun/Oracleの情報を見ることができます。 こちら .