主要问题
最新的 4.x apache http 客户端是否存在我不知道的错误? 或者我缺少让 sni 工作的设置?
在同一 jvm 上/中(在本例中为 1.7.0_45)。
我运行以下两段代码来提取需要 SNI 才能正确连接的 https url。第一段代码使用 java 内置的 java.net.* 方法,第二段代码使用 org.apache.http.*(4.5 版)方法。
使用 java.net.* 的方法
public final class JavaNetHitApi extends BaseHitApi {
@Override
public JSONObject hitAPI(final String url) throws IOException {
URL toUse = new URL(url);
URLConnection conn = toUse.openConnection();
final String result = readToString(conn.getInputStream());
JSONObject toReturn = new JSONObject(result);
return toReturn;
}
}
使用 org.apache.http.* 的方法
public final class ApacheHttpHitApi extends BaseHitApi {
@Override
public JSONObject hitAPI(final String url) throws IOException {
final HttpGet httpGet = new HttpGet(url);
try (final CloseableHttpClient httpclient = HttpClients.createDefault();
final CloseableHttpResponse response = httpclient.execute(httpGet)) {
String result = readToString(response.getEntity().getContent());
JSONObject toReturn = new JSONObject(result);
return toReturn;
}
}
}
对于第一种情况 (java.net.*),它工作正常,并且没有问题地返回。
对于第二种情况 (org.apache.http.*),它会抛出以下错误:
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
请记住,这是在同一个 JVM 上运行的,具有相同的 sni 启用设置等。 我通过搜索所有关于从 Java 1.6->1.7,或 1.7->1.8,或在系统上启用 sni 等的讨论得到的唯一解释。 在这种情况下,所有这些变量都被消除了,因为这两段代码的底层系统设置是相同的。
主要问题回顾
最新的 4.x apache http 客户端是否存在我不知道的错误? 或者我缺少让 sni 工作的设置?
运行时
"-Djavax.net.debug=all"
flag,我可以看到这两种方法的不同之处,即 java.net.* 方法吐出了一行:
Extension server_name, server_name: [host_name: obfuscatedsubdomain.execute-api.us-west-2.amazonaws.com]
而 apache http 客户端没有。
下面包含输出片段以供引用。
java.net.* 输出
Allow unsafe renegotiation: false
Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
main, setSoTimeout(0) called
%% No cached client session
*** ClientHello, TLSv1
RandomCookie: GMT: 1424292809 bytes = { 117, 134, 25, 51, 251, 228, 170, 18, 240, 70, 32, 245, 131, 90, 128, 105, 26, 220, 234, 92, 81, 47, 129, 195, 17, 137, 210, 125 }
Session ID: {}
Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, SSL_RSA_WITH_RC4_128_SHA, TLS_ECDH_ECDSA_WITH_RC4_128_SHA, TLS_ECDH_RSA_WITH_RC4_128_SHA, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_RC4_128_MD5, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
Compression Methods: { 0 }
Extension elliptic_curves, curve names: {secp256r1, sect163k1, sect163r2, secp192r1, secp224r1, sect233k1, sect233r1, sect283k1, sect283r1, secp384r1, sect409k1, sect409r1, secp521r1, sect571k1, sect571r1, secp160k1, secp160r1, secp160r2, sect163r1, secp192k1, sect193r1, sect193r2, secp224k1, sect239k1, secp256k1}
Extension ec_point_formats, formats: [uncompressed]
Extension server_name, server_name: [host_name: obfuscatedsubdomain.execute-api.us-west-2.amazonaws.com]
***
apache.org.http.* 输出
main, setSoTimeout(0) called
Allow unsafe renegotiation: false
Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
%% No cached client session
*** ClientHello, TLSv1
RandomCookie: GMT: 1424293231 bytes = { 222, 180, 202, 14, 219, 36, 94, 157, 23, 55, 5, 98, 165, 33, 227, 160, 201, 191, 122, 194, 241, 154, 216, 137, 159, 81, 208, 143 }
Session ID: {}
Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, SSL_RSA_WITH_RC4_128_SHA, TLS_ECDH_ECDSA_WITH_RC4_128_SHA, TLS_ECDH_RSA_WITH_RC4_128_SHA, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_RC4_128_MD5, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
Compression Methods: { 0 }
Extension elliptic_curves, curve names: {secp256r1, sect163k1, sect163r2, secp192r1, secp224r1, sect233k1, sect233r1, sect283k1, sect283r1, secp384r1, sect409k1, sect409r1, secp521r1, sect571k1, sect571r1, secp160k1, secp160r1, secp160r2, sect163r1, secp192k1, sect193r1, sect193r2, secp224k1, sect239k1, secp256k1}
Extension ec_point_formats, formats: [uncompressed]
***
最佳答案
问题最终是另一个依赖项不仅使用了不同版本的 httpclient,而且还将它打包到它的 jar 中而没有将其列为传递依赖项。 (意思是,当你去检查 pom 依赖层次结构时它不会出现,所以它不能被标记为“使用过的版本”)。
有问题的依赖是:
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-dev</artifactId>
<version>2.7.0</version>
</dependency>
它的 jar 中包含了 apache http 的代码,但未在其 pom.xml 中列出。 它引用的版本是 4.3.1,出现了这个问题。 (4.3.2 及以后没有)。
有两种解决方法:
在 1st 列表中包含 http 客户端依赖项 pom.xml
从 pom.xml 中移除 gwt-dev 依赖
关于java - Apache http 客户端默认值不适用于 sni,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32341729/