Apache http客户端默认设置不适用于sni

初步问题

有没有最新的4.x apache http客户端我不知道的错误? 或者我缺少让sni工作的设置?

在同一个jvm上(在这种情况下为1.7.0_45)。

我运行以下两段代码来提取一个https url,它需要SNI才能正确连接。 第一段代码使用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:收到致命警报: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。*方法吐出了这条线:

扩展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依赖层次结构时它不会显示,所以它不能被标记为“used used”)。

有关的依赖是:

  com.google.gwt gwt-dev 2.7.0  

它的jar包含了apache http的代码,并且在其pom中未列出。 它引用的版本是4.3.1,它表现出这个问题。 (4.3.2及以后不要)。

有两种解决方法:

  1. 在pom.xml中的列表中包含http客户端依赖关系1st

  2. 从pom.xml中删除gwt-dev依赖项