私は、SSLとWebサービスがきめ細かいレベルでどのように機能するかについて、少しばかげています。いくつかのWebサービスを呼び出すシステムを開発しています。一部は安全なURLで、その他はほとんど問題ありません。ただし、現在、EndiciaのLabelServer Web APIとの統合を行っています。 Webサービスは、送料の計算と印刷に使用されます。
テストURLとWSDLは次の場所にあります https://www.envmgr.com/LabelService/EwsLabelService.asmx
Wsimportを使用してJavaこのWebサービスに接続するためのクライアントを作成およびセットアップしましたが、すべてを実行しようとするとエラーが発生します
PKIXパスの検証に失敗しました:Java.security.cert.CertPathValidatorException:パスがどのトラストアンカーともチェーンしていません
このエラーはここに文書化されています: Java7がトラストストアの証明書を信頼することを拒否しています
Java 7は、「不正な」鍵使用の自己署名証明書でエラーを強制します。この状況での不良は、keyCertSignが含まれていないと定義されています。WebサービスはJava 6.テストサーバーとしてのみ使用されているため、この証明書がこの証明書に適用される可能性があると確信できますが、それを確認する方法がわかりません。
解決されたバグレポートがあります( http://bugs.Java.com/bugdatabase/view_bug.do?bug_id=7018897 )が、これがどのように変換されるかはわかりませんWindows Tomcat環境の問題を修正します。証明書を自分のマシンにエクスポートしましたが、そこから続行する方法がわかりません。
編集:OpenSSLを使用して証明書を変更してキーストアに追加しようとしましたが、「トラストストアの証明書を信頼することを拒否する」リンクで説明されているように機能しませんでした。これは証明書の所有者が行うプロセスのようですよね?私のJava 7環境を構成して、この証明書を通過させることができる方法はあるのでしょうか。
デフォルトのJava証明書チェックはかなり厳格で、明らかに厳しくなっています。1つの回避策は、カスタムで SSLContext
を初期化することです _X509TrustManager
_ 。私がかつてテスト用に書いた、何もしない、つまり完全に安全ではないトラストマネージャは、次のようになります。
_TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public Java.security.cert.X509Certificate[] getAcceptedIssuers()
{
return null;
}
public void checkClientTrusted(
Java.security.cert.X509Certificate[] certs,
String authType )
{
}
public void checkServerTrusted(
Java.security.cert.X509Certificate[] certs,
String authType )
{
}
}
};
_
もちろん、実際のプログラムで実際に証明書チェーンをチェックする必要があります。次に、APIでSSLを構成する方法が他にない場合は、それを使用してSSLContext
を初期化し、SSLContext.setDefault()
を呼び出すことができます。 APIがデフォルトのSSLコンテキストを使用している場合、これは機能するはずです。
この場合、証明書チェーンは自己署名されていないため、キーの使用法は問題ではないようです。 URLをテストすると、リーフ証明書が自己署名されておらず、(2)チェーン内の他の2つの証明書で証明書署名が有効になっているように見えます。別の可能性としては、Java 6およびJava 7に個別のトラストストアがあり、ルート証明書がJava 7ストア。OpenSSLにアクセスできる場合は、サーバーから証明書チェーンを取得できます。
_openssl s_client -Host www.example.com -port 443 -showcerts
_
どうやらトラストストアを更新することが鍵でした(意地悪な意図)。 OPは次のように報告します。
OpenSSL for Windows 64をダウンロードし、次のコマンドを使用して証明書チェーンをダウンロードしました。
_openssl s_client -Host www.webserviceurl.com -port 443 -showcerts > c:\temp\certchain_output.crt
_
次に、ブラウザのキーストアに次のようにインポートします(JDKのホームディレクトリ/ jre/lib/securityから)。
_keytool -import -alias ca -file certchain_output.crt -keystore cacerts -storepass changeit
_
X509TrustManagerを使用すると、効果的なソリューションも提供できると思います。
証明書チェーン検証ロジックは、Java 6とJava 7.の間で実際に変更されました。有効期限の終了日が中間証明書がルート証明書の有効終了日より後になっているこれは a Java bug であり、JDK 1.7.0_72および1.8.0_25で修正されました。
JDKをアップグレードできない場合は、デバッグ環境にあり、キーストアを制御できるというので、これが回避策です。もちろん、どの証明書も変更できません(秘密鍵がないため)。ただし、中間証明書またはサーバー証明書をローカルキーストアにインポートできます。つまり、デフォルトで信頼され、残りはチェーンの検証は問題なく行われます。
www.envmgr.com
またはwww.starfieldtech.com
の証明書をtrusted_certificate.pemとしてダウンロードしますkeytool
を使用して、keytool -keystore my_keystore -importcert -file trusted_certificate.pem
でmy_keystoreという名前のローカルキーストアに証明書をインポートしますwsimport -J-Djavax.net.ssl.trustStore=my_keystore https://www.envmgr.com/LabelService/EwsLabelService.asmx
を起動しますKeytoolを使用して、必要な証明書をJavaトラストストアをjdk_xxx/jre/lib/security/cacertsにインポートしてみてください。
詳細なデバッグ情報を表示するには、jvmパラメータDjavax.net.debug = sslを設定します
ラシモトは私に役立つ解決策を見つけるのに役立ちました:
OpenSSL for Windows 64をダウンロードし、次のコマンドを使用して証明書チェーンをダウンロードしました。
openssl s_client -Host www.webserviceurl.com -port 443 -showcerts > c:\temp\certchain_output.crt
次に、ブラウザのキーストアに次のようにインポートします(JDKのホームディレクトリ/ jre/lib/securityから)。
keytool -import -alias ca -file certchain_output.crt -keystore cacerts -storepass changeit
X509TrustManagerを使用すると、効果的なソリューションも提供できると思います。
これを試してみてください、それはすべてを受け入れます
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public Java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; }
public void checkClientTrusted(X509Certificate[] certs, String authType) { }
public void checkServerTrusted(X509Certificate[] certs, String authType) { }
} };
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new Java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
// Create all-trusting Host name verifier
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) { return true; }
};
// Install the all-trusting Host verifier
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);