Apache http 客户端默认设置不适用于 sni [英] Apache http client defaults don't work with sni

查看:40
本文介绍了Apache http 客户端默认设置不适用于 sni的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

主要问题

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

在/在同一个 jvm 中(在本例中为 1.7.0_45).

On/in the same jvm (in this case 1.7.0_45).

我运行以下两段代码来提取需要 SNI 才能正确连接的 https url.第一段代码使用 java 内置的 java.net.* 方法,第二段代码使用 org.apache.http.*(4.5 版)方法.

I run the following two pieces of code to pull an https url that requires SNI for it to connect correctly. The 1st piece of code uses java's built in java.net.* approach, and the 2nd piece of code uses org.apache.http.* (version 4.5) approach.

使用 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.*),它工作正常,并且没有问题返回.


For the 1st case (java.net.*), it works fine, and returns with no problems.

对于第二种情况(org.apache.http.*),它抛出以下错误:

For the 2nd case (org.apache.http.*), it throws the following error:

javax.net.ssl.SSLHandshakeException:收到致命警报:握手_失败

javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

请记住,这是在相同的 JVM 上运行,具有相同的 sni 启用设置等.我在搜索中遇到的唯一解释是从 java 1.6->1.7 或 1.7->1.8 开始,或在系统上启用 sni 等.在这种情况下,所有这些变量都被消除了,因为两段代码的底层系统设置是相同的.

Keep in mind this is running on the same JVM, with the same sni enabled settings, etc. The only explanations I've come across through searching all talk about going from java 1.6->1.7, or 1.7->1.8, or enabling sni on the system, etc. In this case, all those variables are eliminated, since the underlying system settings are the same for both pieces of code.

主要问题回顾

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

当与

"-Djavax.net.debug=all"

"-Djavax.net.debug=all"

flag,我可以看到这两种方法的不同之处,即 java.net.* 方法吐出这一行:

flag, I can see where the two approaches differ, namely that the java.net.* approach spits out the line:

扩展 server_name, server_name: [host_name:obfuscatedsubdomain.execute-api.us-west-2.amazonaws.com]

Extension server_name, server_name: [host_name: obfuscatedsubdomain.execute-api.us-west-2.amazonaws.com]

而 apache http 客户端没有.

And the apache http client does not.

输出片段包含在下面以供参考.

The output snippets are included below for reference.

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 依赖层次结构时它不会出现,所以它不能被标记为使用过的版本").

The issue ended up being that another dependency was not only using a different version of the httpclient, BUT was also packaging it into its jar without listing it as a transitive dependency. (meaning, that it doesn't show up when you go to inspect the pom dependency hierarchy, so it can't be flagged out as the "used version").

有问题的依赖是:

<dependency>
    <groupId>com.google.gwt</groupId>
    <artifactId>gwt-dev</artifactId>
    <version>2.7.0</version>
</dependency>

它的 jar 中包含 apache http 的代码,但在其 pom 中未列出.而它引用的版本是4.3.1,就出现了这个问题.(4.3.2 及以后不会).

It has the code for apache http included in its jar, and unlisted in its pom. And the version it references is 4.3.1, which exhibits this problem. (4.3.2 and onward do not).

有两种解决方法:

  1. 在列表中包含 http 客户端依赖项 1stpom.xml

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

Remove the gwt-dev dependency from the pom.xml

这篇关于Apache http 客户端默认设置不适用于 sni的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆