編集: - 私のところでもっと見やすい方法で質問と受け入れられた答えをフォーマットしようとしましたブログ
これが元の問題です。
私はこのエラーを受けています:
詳細メッセージSun.security.validator.ValidatorException:PKIXパスの構築に失敗しました:
Sun.security.provider.certpath.SunCertPathBuilderException:要求されたターゲットへの有効な証明書パスが見つかりません原因javax.net.ssl.SSLHandshakeException:Sun.security.validator.ValidatorException:PKIXパスの構築に失敗しました:Sun.security.provider.certpath.SunCertPathBuilderException:要求されたターゲットへの有効な証明書パスが見つかりません
WebサーバとしてTomcat 6を使用しています。私は2つのHTTPS Webアプリケーションを異なるポートの異なるTomcatsに同じマシンにインストールしています。 App1(port 8443)
とApp2(port 443)
を言います。 App1
はApp2
に接続します。 App1
がApp2
に接続すると、上記のエラーが発生します。これは非常に一般的なエラーであることを私は知っているので、さまざまなフォーラムやサイトで多くの解決策に出会いました。私は両方のTomcatsのserver.xml
に以下のエントリーを持っています:
keystoreFile="c:/.keystore"
keystorePass="changeit"
すべてのサイトがapp2によって与えられた証明書がapp1 jvmの信頼できるストアにないという同じ理由を言います。これはIEブラウザで同じURLをヒットしようとしたときにも当てはまるようです、それはうまくいきます(警告と共に、このWebサイトのセキュリティ証明書に問題があります。ここで私はこのWebサイトを続けると言います)。しかし、同じURLがJavaクライアントによってヒットされると(私の場合)、上記のエラーが発生します。それでトラストストアに入れるために、私はこれらの3つのオプションを試しました:
オプション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
しかし何も働かなかった 。
ついにうまくいった で提案されたJavaアプローチを実行している - Apache HttpClientで無効なSSL証明書を処理する方法 Pascal Thiventによる、すなわちプログラムInstallCertの実行。
しかし、この方法はdevboxの設定には問題ありませんが、実稼働環境では使用できません。
server.xml
サーバーのapp2
に同じ値を設定し、truststoreに同じ値を設定して参照した場合、上記の3つの方法がうまくいかなかったのはなぜだろう
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());
%Java_HOME%\lib\security\cacerts
にある使用済みJVMのトラストストアファイルに App2 の証明書を追加する必要があります。
まず、次のコマンドを実行して、証明書がすでにトラストストアにあるかどうかを確認できます。keytool -list -keystore "%Java_HOME%/jre/lib/security/cacerts"
(パスワードを入力する必要はありません)
証明書が見つからない場合は、ブラウザで証明書をダウンロードして次のコマンドでトラストストアに追加します。
keytool -import -noprompt -trustcacerts -alias <AliasName> -file <certificate> -keystore <KeystoreFile> -storepass <Password>
インポート後、最初のコマンドをもう一度実行して証明書が追加されたかどうかを確認できます。
Sun/Oracleの情報は ここ にあります。
javax.net.ssl.SSLHandshakeException:Sun.security.validator.ValidatorException:PKIXパス構築に失敗しました:Sun.security.provider.certpath.SunCertPathBuilderException:要求されたターゲットへの有効な証明書パスが見つかりません
•エラーが発生したとき、Googleで表現の意味を調べたところ、この問題はサーバーがHTTPS SSL証明書を変更したときに発生し、古いバージョンのJavaではルート認証局(CA)が認識されません。 。
•ブラウザでHTTPS URLにアクセスできる場合は、ルートCAを認識するようにJavaを更新することが可能です。
•ブラウザで、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 - ファイルPATH_TO_FILENAME_OF_THE_INSTALLED_CERTIFICATE - キーストアPATH_TO_CACERTS_FILE - storepass changeit
•証明書情報をcacertファイルに追加します。
それは私が上記の例外のために見つけた解決策です!
Tomcat Appで自己署名証明書をサポートしたいのですが 次のスニペットが機能しませんでした
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);
}
}
これが私の問題を解決したものです。
.crt
ファイルをダウンロードする echo -n | openssl s_client -connect <your domain>:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > ~/<your domain>.crt
<your domain>
をあなたのドメインに置き換えます(例:jossef.com
)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>
をあなたのドメインに置き換えます(例:jossef.com
)<Java HOME>
をJavaのホームディレクトリに置き換えます。Iv'eがJava
のデフォルトの証明書ストアに私の証明書をインストールしたとしても、 Tomcatは を無視します(Javaのデフォルトの証明書ストアを使うようには設定されていないようです)。
これをハックするには、コードのどこかに次のコードを追加します。
String certificatesTrustStorePath = "<Java HOME>/jre/lib/security/cacerts";
System.setProperty("javax.net.ssl.trustStore", certificatesTrustStorePath);
// ...
私の場合、問題はWebサーバが証明書と中間CAだけを送信し、ルートCAは送信していないことでした。このJVMオプションを追加することで問題が解決しました:-Dcom.Sun.security.enableAIAcaIssuers=true
Authority Information Access拡張のcaIssuersアクセス方法のサポートが利用可能です。互換性のためにデフォルトで無効になっており、システムプロパティ
com.Sun.security.enableAIAcaIssuers
を値trueに設定することで有効にできます。Trueに設定されている場合、証明書のldap、http、またはftpのURIであれば、証明書のAIA拡張機能(指定されたCertStoreに加えて)の情報を使用して発行CA証明書を見つけます。
私のcacertsファイルは完全に空でした。私はこれを解決するためにcacertsファイルを私のwindowsマシンからコピーし(Oracle Java 7を使用している)、それを私のLinuxマシン(OpenJDK)にscpしました。
cd %Java_HOME%/jre/lib/security/
scp cacerts mylinuxmachin:/tmp
そしてLinuxマシンで
cp /tmp/cacerts /etc/ssl/certs/Java/cacerts
これまでのところうまくいっています。
もう1つの理由は、JDKの古いバージョンである可能性があります。私は単に最新版に更新することで証明書の問題を解決しました。
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
を指します。
私にとっては、SSLを処理していたNGINXリバースプロキシの背後にあるプロセスに接続しようとしたときにもこのエラーが発生しました。
証明書チェーン全体が連結されていない証明書が問題であることがわかりました。中間証明書を追加したときに、問題は解決しました。
お役に立てれば。
私は同じ問題に直面したとき私はjdk1.8.0_171
を使っていました。私はここでトップ2の解決策を試してみました(keytoolを使った証明書とそれにハックがあるもう一つの解決策を追加する)が、私にはうまくいきませんでした。
私はJDKを1.8.0_181
にアップグレードしました、そしてそれは魅力のように働きました。
以下のコードは私のために働きます:
import Java.security.cert.CertificateException;
import Java.security.cert.X509Certificate;
import javax.net.ssl.X509TrustManager;
public class TrustAnyTrustManager implements X509TrustManager {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[] {};
}
}
HttpsURLConnection conn = null;
URL url = new URL(serviceUrl);
conn = (HttpsURLConnection) url.openConnection();
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, new TrustManager[]{new TrustAnyTrustManager()}, new Java.security.SecureRandom());
conn.setSSLSocketFactory(sc.getSocketFactory());
私はプログラムファイル内のすべてのJavaのバージョンを検索し、それらに証明書を追加する小さなwin32(WinXP 32ビットのtestet)愚かなcmd(コマンドライン)スクリプトを書いた。パスワードはデフォルトの "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
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 fileはここにあります。信頼できない証明書を挿入します。
私もこの問題を抱えています。
SSL証明書を.keystoreに追加して、ほとんどすべてのことを試しましたが、Java1_6_xでは機能しませんでした。私にとっては、JVMとして新しいバージョンのJava、Java1_8_xを使い始めるのに役立ちました。
以下のMacOS Xでは、 'importcert'オプションでダブルハイフンを試してみる必要があったところ、私にとって正確に使えるコマンドは以下のとおりです。
Sudo keytool -–importcert -file /PathTo/YourCertFileDownloadedFromBrowserLockIcon.crt -keystore /Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/lib/security/cacerts -alias "Cert" -storepass changeit
安全のために、実装に自己署名証明書を使用しないでください。しかし、開発に関しては、自己署名証明書を取得した試用環境を使用する必要があります。私は自分のコードでプログラム的にこの問題を解決しようとしましたが失敗しました。しかし、証明書をjre trust-storeに追加することで問題が解決しました。以下の手順を見つけてください、
サイト証明書をダウンロードしてください。
証明書(例:cert_file.cer)をディレクトリ$ Java_HOME\Jre\Lib\Securityにコピーします。
AdministratorでCMDを開き、ディレクトリを$ Java_HOME\Jre\Lib\Securityに変更します。
Belowコマンドを使用して証明書をトラストストアにインポートします。
keytool -import -alias ca -file cert_file.cer -keystore cacerts -storepass changeit
keytoolが認識できないというエラーが表示された場合は、 こちらを参照してください。
以下のように yes と入力します。
この証明書を信頼します。 [はい]
更新
アプリサーバーがjbossの場合は、以下にシステムプロパティを追加してみてください。
System.setProperty("org.jboss.security.ignoreHttpsHost","true");
お役に立てれば!
AndroidStudio
、Charles Proxy
、JUnit
、Robolectric
を使ってこの問題に遭遇しました。ありがとう@SimonSez私は問題を解決することができました。
%Java_HOME%
- Androidは別のJavaHomeを使用しています。フルパスはRun
UnitTests
ウィンドウにあります。私の場合は/Applications/Android Studio.app/Contents/jre/jdk/Contents/Home
ですDownloads
フォルダーにダウンロードしますコマンドを実行する
Sudo keytool -import -noprompt -trustcacerts -alias charles -file ~/Downloads/charles-ssl-proxying-certificate.pem -keystore "/Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/jre/lib/security/cacerts" -storepass changeit