本文介绍了服务器关闭使用httpclient和Java 7建立的连接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试连接到使用SNI提供证书的远程服务器。我注意到服务器正在关闭使用Java 7编译和运行代码时的连接,而不是在我通过Java 8编译和运行代码时。

I am trying to connect to a remote server that serves certificates using SNI. I noticed that the server is closing connections made when I compile and run code using Java 7 and not when I compile and run it via Java 8.

下面是代码我做了测试这个假设。我切换Java版本并运行代码并获得不同的结果。

Below is the code that i made to test this assumption. I switch Java versions and run the code and get different results.

public static void getRequest() throws IOException, NoSuchAlgorithmException, KeyManagementException {
    String url = "https://sorry i can not share the exact url because of privacy concerns";

    HttpClient client = getClientInstance();
    HttpGet request = new HttpGet(url);

    HttpResponse response = client.execute(request);

    System.out.println("Response Code : "
            + response.getStatusLine().getStatusCode());

    BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));

    StringBuffer result = new StringBuffer();
    String line = "";
    while ((line = rd.readLine()) != null) {
        result.append(line);
    }
    System.out.println("####### the result is");
    System.out.println(result.toString());
}

private static org.apache.http.client.HttpClient getClientInstance() throws KeyManagementException, NoSuchAlgorithmException {
    RequestConfig defaultRequestConfig = RequestConfig.copy(RequestConfig.DEFAULT)
            .setConnectTimeout(60 * 1000)
            .setSocketTimeout(60 * 1000)
            .setConnectionRequestTimeout(60 * 1000)
            .build();

    return HttpClientBuilder.create().setDefaultRequestConfig(defaultRequestConfig).build();
}

有人遇到过这样的问题并修好了吗?我知道最终的解决方案是使用Java 8,但这不是我在当前时间限制内可以完成的任务,因为我调试的整个代码库非常庞大,并且具有可能与Java 7不兼容的依赖项。

Has someone ever experienced such an issue and fixed it? I know the ultimate fix would be to use Java 8 but that's not a task that I can do within my current time constraints since the entire codebase i was debugging is huge and has dependencies that might not work well with Java 7.

抛出的异常如下;

*** ClientHello, TLSv1
RandomCookie:  GMT: 1472095425 bytes = { 254, 51, 194, 246, 77, 6, 185, 8, 224, 187, 85, 225, 133, 128, 122, 1, 245, 13, 230, 239, 156, 93, 164, 184, 251, 159, 111, 60 }
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_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, 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, 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: lasclev.org]
***
main, WRITE: TLSv1 Handshake, length = 169
main, handling exception: java.net.SocketException: Connection reset
main, SEND TLSv1 ALERT:  fatal, description = unexpected_message
main, WRITE: TLSv1 Alert, length = 2
main, Exception sending alert: java.net.SocketException: Broken pipe
main, called closeSocket()
java.net.SocketException: Connection reset
    at java.net.SocketInputStream.read(SocketInputStream.java:196)
    at java.net.SocketInputStream.read(SocketInputStream.java:122)
    at sun.security.ssl.InputRecord.readFully(InputRecord.java:442)
    at sun.security.ssl.InputRecord.read(InputRecord.java:480)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:934)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1332)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1359)

下面是我之前执行的SSL实验室测试的屏幕截图。

Also below is a screenshot of the SSL Labs test that i carried out earlier.

推荐答案

您没有显示部分内容SSLLabs报告它列出了支持的协议,但我敢打赌你会发现这个服务器只支持TLSv1.2或TLSv1.2和TLSv1.1,但不支持TLSv1.0。特别是,处理受PCI DSS支付的支付交易的系统通常被禁止使用TLSv1.0(又名早期TLS),这显然是由于对BEAST的过度反应(尽管它不值得,但在NVD中仍为4.3)。虽然在这种情况下服务器提供警报70或71或40而不仅仅是重置(或关闭)。 Java7(JSSE)客户端默认不执行TLSv1.2或TLSv1.1。

You didn't show the part of the SSLLabs report where it lists protocols supported, but I bet you'll find this server supports only TLSv1.2 or maybe TLSv1.2 and TLSv1.1, but not TLSv1.0. In particular, systems handling payment transactions subject to PCI DSS are generally prohibited from using TLSv1.0 (aka 'Early TLS') apparently due to an overreaction to BEAST (which remains 4.3 in NVD although it doesn't deserve to). Although in this case the server should give alert 70 or maybe 71 or 40 not just reset (or close). Java7 (JSSE) client by default does not do TLSv1.2 or TLSv1.1.

它可能取决于HttpClient的版本 - 我有4.5 - 但我认为你可以:

It may depend on the version of HttpClient -- I have 4.5 -- but I think you can either:


  • 创建一个适当配置的 SSLConnectionSocketFactory .setSSLSocketFactory 到它,或

。 useSystemProperties(true)并根据需要设置sysprop https.protocols TLSv1.2 TLSv1.1,TLSv1.2 (也由 javax.net.HttpsURLConnection 使用),但这可能会影响其他事物你不想要(参见javadoc for useSystemProperties

.useSystemProperties(true) and set sysprop https.protocols as appropriate either TLSv1.2 or TLSv1.1,TLSv1.2 (also used by javax.net.HttpsURLConnection), but this may affect other things you don't want (see the javadoc for useSystemProperties)

这篇关于服务器关闭使用httpclient和Java 7建立的连接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-14 00:23