8

Java アプリケーションでは、https プロトコルを使用して SSL 上のサーバーのリストと通信する必要があります。通信するサーバーのリストは、実行時に変更されます。最初は、サーバーの証明書はありません。実行時に、新しいサーバーの証明書を取得し、公開鍵証明書をトラストストアに追加します。また、サーバーとの新しい https 接続はすべて、更新されたトラスト ストアを使用する必要があります。

1 つは cacerts (jre に付属するデフォルトのもの) で、もう 1 つはリストで動的に追加/削除するサーバーの証明書を含む 2 つのトラスト ストアを使用する必要があると考えています。これにより、Java のデフォルトの TrustStore (cacerts) を変更しないことが保証されます。

これを達成する方法を提案してください。また、特定のトラスト ストアを Java の特定のスレッドにのみ使用する方法はありますか? そのため、他の (既存および新規の) スレッドは引き続きデフォルトの Java trueststore(cacerts) を使用する必要があり、1 つの特定のスレッドが特定のトラストストアを使用します。サーバー。

ありがとう、ディーパック

4

2 に答える 2

5

証明書を動的にインポートする場合は、カスタムx509TrustManager. これは、またはSSLContextの作成に使用されるの設定時に行われます。SSLSocketFactorySSLEngine

jSSLutilsは、既存のトラスト マネージャーをラップし、特定の設定をカスタマイズできるライブラリです。必要ありませんが、役立つ場合があります。

これは次のようになります。

PKIXSSLContextFactory sslContextFactory = new PKIXSSLContextFactory();
sslContextFactory.setTrustManagerWrapper(new X509TrustManagerWrapper() {
    @Override
    public X509TrustManager wrapTrustManager(final X509TrustManager origManager) {
        return new X509TrustManager() { 
            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return origManager.getAcceptedIssuers();
            }

            @Override
            public void checkServerTrusted(X509Certificate[] chain,
                                                   String authType)
                    throws CertificateException {
                try {
                    // This will call the default trust manager
                    // which will throw an exception if it doesn't know the certificate
                    origManager.checkServerTrusted(chain, authType);
                } catch (CertificateException e) {
                    // If it throws an exception, check what this exception is
                    // the server certificate is in chain[0], you could
                    // implement a callback to the user to accept/refuse
                }
            }

            @Override
            public void checkClientTrusted(X509Certificate[] chain,
                                                   String authType)
                    throws CertificateException {
                origManager.checkClientTrusted(chain, authType);
            }
        };
    }
});
SSLContext sslContext = sslContextFactory.buildSSLContext();

((PKIX)SSLContextFactoryX509TrustManagerWrapperは jSSLutils から来ていますが、残りは J2SE/J2EE で利用できます。)

キャッチしたい がいくつかあります (サブクラスを参照してくださいCertificateException)。ユーザーにコールバックを行う場合、SSL/TLS ハンドシェイクのタイムアウトが原因で、SSL/TLS 接続が最初に失敗する可能性があります (コールバックの応答に時間がかかりすぎる場合)。

SSLContextこれを (Java 6 から)デフォルトとして使用できますが、それSSLContext.setSSLContext(...)は必ずしも良い考えではありません。可能であればSSLContext、SSL/TLS 接続を確立するライブラリに を渡します。これがどのように行われるかはさまざまですが、たとえば Apache HTTP Client 4.x には SSL 設定を構成するための複数のオプションがあり、そのうちの 1 つはKeyStores を渡し、もう 1 つはSSLContext.

また、接続しようとしているオブジェクトごとではなく、スレッドごとに何かを行うこともできます (ライブラリに依存) X509TrustManager。トラストマネージャー。

于 2010-09-09T09:46:57.727 に答える
2

この質問はとても古いので、私のビットが誰にも役立つのではないかと疑っていますが、ここに行きます...

コードの変更に頼らずに OP (元のポスター) の問題を解決したい場合は、OP の目的の構成をサポートするように JVM (私は Tomcat でのみテストしました) を構成できます。

  1. 「パッケージ化された」JDK cacerts ファイルはそのままにしておきます
  2. 証明書を別のファイルにインポートし、JAVA アプリに証明書を「信頼」させる

以前は、追加の証明書を別のファイルにインポートしてから、JVM スタートアップでパラメータ-Djavax.net.ssl.trustStore=$JAVA_HOME/jre/lib/security/jssecacertsを使用して参照するだけで成功していましたが、最近の (多少の) JAVA セキュリティの問題により、SDK で配布される cacerts ファイルの自動インクルードが変更されたと思います。

そこで、この投稿とこれらのページからインテルを使用した気の利いた解決策を見つけました(いくつかの小さな変更を加えて):

私がしていたこと:

  • 次のように、JVM trustStore パラメーターを別のキーストア ファイル (追加の証明書をインポートするファイル) に設定します。

私が今やっていること:

  • trustStore パラメーターを「パッケージ化された」cacerts ファイルに設定します
  • keyStore パラメーターを「追加の証明書」ファイルに設定します
  • keyStorePassword パラメーターをキーストアのパスワードに設定します (デフォルトは changeit です)

それはどのようなものか:

-Djavax.net.ssl.trustStore=$JAVA_HOME/jre/lib/security/cacerts \
-Djavax.net.ssl.keyStore=$JAVA_HOME/jre/lib/security/jssecacerts \
-Djavax.net.ssl.keyStorePassword="changeit" \

これが誰かに役立つことを願っています。trustStoreを使用していないため、keyStoreパスワードを指定する必要があるとは100%ではありませんが、指定すると機能します。

于 2013-01-26T13:22:49.680 に答える