java - Apache http 客户端默认值不适用于 sni

标签 java apache-httpclient-4.x

主要问题

最新的 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 及以后没有)。

有两种解决方法:

  1. 1st 列表中包含 http 客户端依赖项 pom.xml

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

关于java - Apache http 客户端默认值不适用于 sni,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32341729/

相关文章:

jmeter - Apache JMeter 是否支持 http/2 请求?

java - 使用混淆器时的异常行为

java - Websphere httpclient NoSuchMethodError org.apache.http.conn.Scheme

java - 如何使用 Apache HttpClient 启用 SSLv3?

java - 如何在 Apache 异步客户端中配置允许的挂起请求数

java - Apache HTTPClient 4.3.3 执行 GET 请求 block 的方法并且从不返回

java - 监听 TableView 处于焦点时触发的后退键事件

java - 通过 HTTP 使用 Commons-VFS

java - 无法打开文本文件

java - 如何使用文件库io Java