大規模なJavaアプリケーションに追加するモジュールは、他の会社のSSLで保護されたWebサイトと対話する必要があります。問題は、サイトが自己署名証明書を使用していることです。中間者攻撃を受けていないことを確認するための証明書のコピーがあり、サーバーへの接続が成功するようにこの証明書をコードに組み込む必要があります。
基本的なコードは次のとおりです。
void sendRequest(String dataPacket) {
String urlStr = "https://host.example.com/";
URL url = new URL(urlStr);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setMethod("POST");
conn.setRequestProperty("Content-Length", data.length());
conn.setDoOutput(true);
OutputStreamWriter o = new OutputStreamWriter(conn.getOutputStream());
o.write(data);
o.flush();
}
自己署名証明書の追加処理がない場合、これはconn.getOutputStream()で終了しますが、次の例外があります。
Exception in thread "main" javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
....
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
....
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
理想的には、私のコードは、アプリケーション内のこの1つの場所のために、この1つの自己署名証明書を受け入れるようにJavaに教える必要があります。
証明書をJREの認証局ストアにインポートでき、Javaがそれを受け入れることができることを知っています。それが私が手助けできるなら私がとりたいアプローチではありません。お客様のすべてのマシンで、使用してはならない1つのモジュールを実行することは非常に侵襲的です。同じJREを使用する他のすべてのJavaアプリケーションに影響します。このサイトにアクセスする他のJavaアプリケーションの確率がゼロであっても、私はそれが好きではありません。これも簡単な操作ではありません。UNIXでは、この方法でJREを変更するためにアクセス権を取得する必要があります。
また、カスタムチェックを行うTrustManagerインスタンスを作成できることも確認しました。この1つの証明書を除くすべてのインスタンスで、実際のTrustManagerに委任するTrustManagerを作成することもできるようです。しかし、TrustManagerはグローバルにインストールされるようで、アプリケーションからの他のすべての接続に影響を与えると思いますが、それも私にはまったく適切な匂いではありません。
自己署名証明書を受け入れるようにJavaアプリケーションを設定するための推奨、標準、または最良の方法は何ですか?上記で考えているすべての目標を達成できますか、それとも妥協する必要がありますか?ファイルとディレクトリ、構成設定、およびほとんどないコードを含むオプションはありますか?