2017-03-07 148 views
1

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

以下是我为测试此假设而做的代码。我切换Java版本并运行代码并获得不同的结果。

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一起使用。

抛出的异常如下所示;

*** 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实验室测试的屏幕截图。 SSL Labs test fragment

回答

2

你没有表现出SSLLabs报告,它里面列出支持的协议的一部分,但我敢打赌,你会发现这个服务器仅支持TLSv1.2工作也许TLSv1.2工作和TLSv1.1,但不使用TLSv1 0.0。特别是,受到PCI DSS支付的支付交易系统通常被禁止使用TLSv1.0(又名'早期TLS'),这显然是由于对BEAST过度反应(尽管NVD中仍然不适用4.3)。虽然在这种情况下服务器给予警报70或可能71或40不只是重置(或关闭)。 Java7(JSSE)客户端默认不会执行TLSv1.2或TLSv1.1。

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

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

  • .useSystemProperties(true)并将sysprop https.protocols设置为​​或TLSv1.1,TLSv1.2(也用于javax.net.HttpsURLConnection),但这可能会影响其他您不想要的内容(请参阅javadoc的useSystemProperties

+0

你的建议是完全合理的,但它对我无效。远程服务器是我无法控制的东西。由于时间的限制,我通过使用'Runtime.getRuntime()。exec'来制作一个令人讨厌的解决方法。 – ivanorone