Сервер закрывает соединения, выполненные с использованием httpclient и Java 7
Я пытаюсь подключиться к удаленному серверу, который обслуживает сертификаты с использованием SNI. Я заметил, что сервер закрывает соединения, сделанные, когда я компилирую и запускаю код, используя Java 7, а не когда я компилирую и запускаю его через Java 8.
Ниже приведен код, который я сделал, чтобы проверить это предположение. Я переключаю версии 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 Labs, который я провел ранее.
1 ответ
Вы не показали ту часть отчета SSLLabs, в которой перечислены поддерживаемые протоколы, но я уверен, что этот сервер поддерживает только TLSv1.2 или, возможно, TLSv1.2 и TLSv1.1, но не TLSv1.0. В частности, системам, обрабатывающим платежные транзакции в соответствии с PCI DSS, обычно запрещается использовать TLSv1.0 (он же "Ранний TLS"), по-видимому, из-за чрезмерной реакции на BEAST (которая остается равной 4,3 в NVD, хотя и не заслуживает этого). Хотя в этом случае сервер должен дать предупреждение 70 или, может быть, 71 или 40, а не просто сбросить (или закрыть). Клиент Java7 (JSSE) по умолчанию не поддерживает TLSv1.2 или TLSv1.1.
Это может зависеть от версии HttpClient - у меня есть 4.5 - но я думаю, что вы можете либо:
создать соответствующим образом настроенный
SSLConnectionSocketFactory
а также.setSSLSocketFactory
к нему или.useSystemProperties(true)
и установить сиспропhttps.protocols
в зависимости от обстоятельствTLSv1.2
или жеTLSv1.1,TLSv1.2
(также используетсяjavax.net.HttpsURLConnection
), но это может повлиять на другие вещи, которые вы не хотите (см. Javadoc дляuseSystemProperties
)