この回答は遅れていますが、私たちは問題にぶつかりました(私はそれを信じることはできませんが、非常に大きなバグです)。
すべてが真実だと思われますが、デフォルトのHostnameVerifierではありませんが、トラブルシューティング担当者です。 (ソケットがSSLSocketImplの場合のみ)HttpsClient DO afterConnectが最初setHostを確立しようとすると:あなたはオーバーライドのcreateSocket()(パラメータなしのメソッド)を使用せずに、カスタムのSSLSocketFactoryを使用している場合
SSLSocketFactory factory = sslSocketFactory;
try {
if (!(serverSocket instanceof SSLSocket)) {
s = (SSLSocket)factory.createSocket(serverSocket,
host, port, true);
} else {
s = (SSLSocket)serverSocket;
if (s instanceof SSLSocketImpl) {
((SSLSocketImpl)s).setHost(host);
}
}
} catch (IOException ex) {
// If we fail to connect through the tunnel, try it
// locally, as a last resort. If this doesn't work,
// throw the original exception.
try {
s = (SSLSocket)factory.createSocket(host, port);
} catch (IOException ignored) {
throw ex;
}
}
は、十分にパラメータ化のcreateSocketを使用して、すべてのさ期待どおりに動作します(クライアントsniの拡張機能を使用)。しかし、それが使われているときに、第2の方法(setHostエンSSLSocketImplにしてみてください)のコードが実行される:
// ONLY used by HttpsClient to setup the URI specified hostname
//
// Please NOTE that this method MUST be called before calling to
// SSLSocket.setSSLParameters(). Otherwise, the {@code host} parameter
// may override SNIHostName in the customized server name indication.
synchronized public void setHost(String host) {
this.host = host;
this.serverNames =
Utilities.addToSNIServerNameList(this.serverNames, this.host);
}
コメントはすべて言います。クライアントハンドシェイクの前にsetSSLParametersを呼び出す必要があります。デフォルトのHostnameVerifierを使用すると、HttpsClientはsetSSLParametersを呼び出します。しかし、逆の方法でsetSSLParametersの実行はありません。この修正はOracleにとって非常に簡単です。
SSLParameters paramaters = s.getSSLParameters();
if (isDefaultHostnameVerifier) {
// If the HNV is the default from HttpsURLConnection, we
// will do the spoof checks in SSLSocket.
paramaters.setEndpointIdentificationAlgorithm("HTTPS");
needToCheckSpoofing = false;
}
s.setSSLParameters(paramaters);
Java 9はSNIで期待どおり動作しています。しかし、彼ら(オラクル)は、この問題を解決するために必要ではないようだ。
ネットワークトレースをキャプチャして、tomcatでSNI指標を送信することができますか? httpsリクエストを作成するコードは何ですか? –
SNIは魔法のようにSSL接続に追加されませんが、SSL接続を確立するコードで使用する必要があります。すべてのHTTPライブラリがそれを行うわけではありません。私の推測では、SNIがあるケースでは使用されるが、他のケースでは使用されないように、小さなテストプログラムとは違って、TomcatでURLアクセスに別のライブラリまたはコードを使用していると思います。 –
コマンドラインで '-Djavax.net.debug = ssl'を使用してJavaのSSLメッセージ(_e.g._)のデバッグを有効にして、Javaクライアントが送受信しているものを正確に確認できます。 – Castaglia