如何在java中设置SSL协议版本?我怎么知道哪一个?接收致命警报:协议版本。

时间:2020-12-14 20:29:09

I am using Apache HttpClient 4.3 to interact with the API of hubic.com. My minimal reproducable example is just a one liner:

我正在使用Apache HttpClient 4.3与hubic.com的API进行交互。我的最小可复制示例只是一个一行:

HttpClientBuilder.create().build().execute(new HttpGet("https://hubic.com"));

However that throws:

然而,将:

Exception in thread "main" javax.net.ssl.SSLException: Received fatal alert: protocol_version
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:208)
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
    at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1991)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1104)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1343)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1371)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1355)
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:275)
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:254)
    at org.apache.http.impl.conn.HttpClientConnectionOperator.connect(HttpClientConnectionOperator.java:117)
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:314)
    at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:363)
    at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:219)
    at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:195)
    at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:86)
    at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:108)
    at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:186)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:106)

Here is the output if I run with System.setProperty("javax.net.debug", "all");:

如果我使用System.setProperty(“javax.net.debug”,“all”)运行,这里是输出。

trustStore is: /usr/lib/jvm/java-8-oracle/jre/lib/security/cacerts
trustStore type is : jks
trustStore provider is : 
init truststore

adding as trusted cert: [... extremely large list ...]

trigger seeding of SecureRandom
done seeding SecureRandom
Ignoring unavailable cipher suite: TLS_DHE_DSS_WITH_AES_256_GCM_SHA384
Ignoring unavailable cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA
Ignoring unavailable cipher suite: TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
Ignoring unavailable cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
Ignoring unavailable cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
Ignoring unavailable cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256
Ignoring unavailable cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA
Ignoring unavailable cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
Ignoring unavailable cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
Ignoring unavailable cipher suite: TLS_RSA_WITH_AES_256_GCM_SHA384
Ignoring unavailable cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
Ignoring unavailable cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
Ignoring unavailable cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
Ignoring unavailable cipher suite: TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
Ignoring unavailable cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
Ignoring unavailable cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
Ignoring unavailable cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
Ignoring unavailable cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
Ignoring unavailable cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA
Ignoring unavailable cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
Ignoring unavailable cipher suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
Allow unsafe renegotiation: false
Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 for SSLv3
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 for SSLv3
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_128_CBC_SHA256 for SSLv3
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 for SSLv3
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 for SSLv3
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 for SSLv3
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 for SSLv3
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 for TLSv1
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 for TLSv1
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_128_CBC_SHA256 for TLSv1
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 for TLSv1
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 for TLSv1
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 for TLSv1
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 for TLSv1
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 for TLSv1.1
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 for TLSv1.1
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_128_CBC_SHA256 for TLSv1.1
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 for TLSv1.1
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 for TLSv1.1
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 for TLSv1.1
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 for TLSv1.1
%% No cached client session
*** ClientHello, TLSv1.2
RandomCookie:  GMT: 1402182685 bytes = { 227, 155, 148, 161, 7, 104, 221, 182, 254, 133, 216, 198, 118, 211, 223, 229, 43, 82, 207, 1, 102, 245, 112, 117, 253, 69, 43, 162 }
Session ID:  {}
Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, 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_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, 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 signature_algorithms, signature_algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA224withECDSA, SHA224withRSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA, MD5withRSA
Extension server_name, server_name: [type=host_name (0), value=hubic.com]
***
[write] MD5 and SHA1 hashes:  len = 225
0000: 01 00 00 DD 03 03 54 94   9C 1D E3 9B 94 A1 07 68  ......T........h
0010: DD B6 FE 85 D8 C6 76 D3   DF E5 2B 52 CF 01 66 F5  ......v...+R..f.
0020: 70 75 FD 45 2B A2 00 00   46 C0 23 C0 27 00 3C C0  pu.E+...F.#.'.<.
0030: 25 C0 29 00 67 00 40 C0   09 C0 13 00 2F C0 04 C0  %.).g.@...../...
0040: 0E 00 33 00 32 C0 2B C0   2F 00 9C C0 2D C0 31 00  ..3.2.+./...-.1.
0050: 9E 00 A2 C0 08 C0 12 00   0A C0 03 C0 0D 00 16 00  ................
0060: 13 C0 07 C0 11 00 05 C0   02 C0 0C 00 04 00 FF 01  ................
0070: 00 00 6E 00 0A 00 34 00   32 00 17 00 01 00 03 00  ..n...4.2.......
0080: 13 00 15 00 06 00 07 00   09 00 0A 00 18 00 0B 00  ................
0090: 0C 00 19 00 0D 00 0E 00   0F 00 10 00 11 00 02 00  ................
00A0: 12 00 04 00 05 00 14 00   08 00 16 00 0B 00 02 01  ................
00B0: 00 00 0D 00 1A 00 18 06   03 06 01 05 03 05 01 04  ................
00C0: 03 04 01 03 03 03 01 02   03 02 01 02 02 01 01 00  ................
00D0: 00 00 0E 00 0C 00 00 09   68 75 62 69 63 2E 63 6F  ........hubic.co
00E0: 6D                                                 m
main, WRITE: TLSv1.2 Handshake, length = 225
[Raw write]: length = 230
0000: 16 03 03 00 E1 01 00 00   DD 03 03 54 94 9C 1D E3  ...........T....
0010: 9B 94 A1 07 68 DD B6 FE   85 D8 C6 76 D3 DF E5 2B  ....h......v...+
0020: 52 CF 01 66 F5 70 75 FD   45 2B A2 00 00 46 C0 23  R..f.pu.E+...F.#
0030: C0 27 00 3C C0 25 C0 29   00 67 00 40 C0 09 C0 13  .'.<.%.).g.@....
0040: 00 2F C0 04 C0 0E 00 33   00 32 C0 2B C0 2F 00 9C  ./.....3.2.+./..
0050: C0 2D C0 31 00 9E 00 A2   C0 08 C0 12 00 0A C0 03  .-.1............
0060: C0 0D 00 16 00 13 C0 07   C0 11 00 05 C0 02 C0 0C  ................
0070: 00 04 00 FF 01 00 00 6E   00 0A 00 34 00 32 00 17  .......n...4.2..
0080: 00 01 00 03 00 13 00 15   00 06 00 07 00 09 00 0A  ................
0090: 00 18 00 0B 00 0C 00 19   00 0D 00 0E 00 0F 00 10  ................
00A0: 00 11 00 02 00 12 00 04   00 05 00 14 00 08 00 16  ................
00B0: 00 0B 00 02 01 00 00 0D   00 1A 00 18 06 03 06 01  ................
00C0: 05 03 05 01 04 03 04 01   03 03 03 01 02 03 02 01  ................
00D0: 02 02 01 01 00 00 00 0E   00 0C 00 00 09 68 75 62  .............hub
00E0: 69 63 2E 63 6F 6D                                  ic.com
[Raw read]: length = 5
0000: 15 03 00 00 02                                     .....
[Raw read]: length = 2
0000: 02 46                                              .F
main, READ: SSLv3 Alert, length = 2
main, RECV TLSv1.2 ALERT:  fatal, protocol_version
main, called closeSocket()
main, handling exception: javax.net.ssl.SSLException: Received fatal alert: protocol_version

No exception is thrown if I try to access e.g. https://google.com. So it guess SSL with Java cannot be completely broken on my system but it has to do with the combination with hubic.com.

如果我尝试访问例如https://google.com,就不会有任何异常。因此,我的系统不能完全破坏SSL,但它与hubic.com的结合有关。

The error protocol_version is not very helpful, but in this question it is suggested that my client uses another protocol version than the server (I guess "server and client could not agree on a protocol" would be more accurate).

错误协议版本不是很有帮助,但是在这个问题中,建议我的客户机使用另一个协议版本(我想“服务器和客户机不能在协议上达成一致”会更准确)。

How do I figure out which protocol versions the server will agree on and how do I enable those in my client? And should I worry about the issue (e.g. like does hubic only allow an old unsupported protocol? (Firefox certainly does not complain about anything unsecure).

如何确定服务器会同意哪些协议版本,以及如何在客户机中启用它们?我是否应该担心这个问题(例如,hubic只允许一个旧的不受支持的协议?)(Firefox当然不会抱怨任何不安全的东西)。

4 个解决方案

#1


7  

I see from the debug that Java does a TLS1.2 handshake instead of the more common SSLv23 handshake:

我从调试中看到,Java做了TLS1.2握手,而不是更常见的SSLv23握手:

main, WRITE: TLSv1.2 Handshake, length = 225
[Raw write]: length = 230
0000: 16 03 03 00
         ^^^^^ - TLS1.2 (SSL3.3)

The server itself can do only TLS1.0 and fails to just announce this older version. I'm not familiar with Java, but you either need set the protocol version to TLSv1 or SSLv23 to speak with this server.

服务器本身只能执行TLS1.0,并且不能只宣布这个旧版本。我不熟悉Java,但是您可能需要将协议版本设置为TLSv1或SSLv23来与此服务器对话。

The following code would set only TLSv1 with Apache HttpClient:

下面的代码将只设置与Apache HttpClient的TLSv1:

HttpClientBuilder
  .create()
  .setSslcontext(SSLContexts.custom().useProtocol("TLSv1").build())
  .build()
  .execute(new HttpGet("https://hubic.com"));

EDIT to include question from comment:

编辑以包括评论的问题:

If you say that the server "fails to just announce this older version", does that mean that the server is misconfigured? In this case, why don't Firefox&Chromium have any problems?

如果您说服务器“不只是宣布这个旧版本”,这是否意味着服务器被错误配置了?在这种情况下,为什么Firefox&Chromium没有任何问题呢?

If the client announces TLS1.2 in the ClientHello and the server can do only TLS1.0 it should announce this, i.e. reply with TLS1.0. The client can then close the connection if TLS1.0 is not good enough or continue with TLS1.0. But, in this case the server just told the client that it does not like this version and closed the connection. Firefox and others instead do a SSLv23 announcement, where they do a TLS1.0 handshake but also announce the best protocol version they support. This usually works good for older servers starting from SSL3.0 but also for newer servers.

如果客户在ClientHello中宣布TLS1.2,而服务器只能执行TLS1.0,则应该声明这个,即使用TLS1.0进行回复。如果TLS1.0不够好或继续使用TLS1.0,客户端可以关闭连接。但是,在这种情况下,服务器只是告诉客户机它不喜欢这个版本并关闭连接。Firefox和其他浏览器则采用SSLv23声明,在那里他们进行了TLS1.0的握手,同时也宣布了他们支持的最好的协议版本。这通常适用于从SSL3.0开始的旧服务器,但也适用于较新的服务器。

You can check the behavior of the server with a recent Perl/IO::Socket::SSL and this script.

您可以使用最近的Perl/IO::Socket::SSL和这个脚本检查服务器的行为。

$ perl analyze-ssl.pl hubic.com
-- hubic.com port 443
 * maximum SSL version  : TLSv1 (SSLv23)
 * supported SSL versions with handshake used and preferred cipher(s):
   * handshake protocols ciphers
   * SSLv23    TLSv1     AES256-SHA
   * TLSv1_2   FAILED: SSL connect attempt failed error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number
   * TLSv1_1   FAILED: SSL connect attempt failed error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number
   * TLSv1     TLSv1     AES256-SHA
   * SSLv3     FAILED: SSL connect attempt failed because of handshake problems error:1409442E:SSL routines:SSL3_READ_BYTES:tlsv1 alert protocol version

Here you can see, that the hosts supports SSLv23 and TLSv1 handshakes, but not the used TLSv1_2 handshake.

在这里您可以看到,主机支持SSLv23和TLSv1握手,而不是使用的TLSv1_2握手。

#2


1  

HttpClient can take an SSLContext for its SSLConnectionSocketFactory.

HttpClient可以为它的SSLConnectionSocketFactory获取SSLContext。

You can set the appropriate TLS version in the properties for the SSLContext with the getInstance static method.

您可以使用getInstance静态方法在SSLContext的属性中设置适当的TLS版本。

Something like SSLContext context = SSLContext.getInstance("TLSv1");

类似SSLContext上下文= SSLContext. getinstance(“TLSv1”);

If you need to force just one protocol (as getInstance can return one that supports multiple protocols), you can use the setEnabledProtocols method (which takes a String[]) on the context you retrieved using getInstance.

如果您只需要强制一个协议(因为getInstance可以返回一个支持多个协议的协议),那么您可以使用setenabledprotocol方法(它接受一个字符串[])在您使用getInstance检索的上下文中。

#3


1  

I have also come across this issue. Certain sites are not accessible, throwing the mysterious: javax.net.ssl.SSLException: Received fatal alert: protocol_version

我也遇到过这个问题。某些站点是不可访问的,抛出了神秘的:javax.net. sslxception:收到了致命警告:协议版本。

I have tried to mend it, following some of the hints given here, but without success. At one point the usual thought “it used to work before..”, really started nagging me.

我试着去修补它,遵循了这里给出的一些提示,但没有成功。在某一点上,通常的想法是“以前工作过……”,真的开始唠叨我了。

Initially I had assumed something had changed in the site I tried to connect to. However, as this is a legacy kind of site, it wasn’t so likely. So, what else could it be..? At one point I thought “Java version”. Unlikely, but maybe worth a try.

起初,我以为我尝试连接的网站发生了一些变化。然而,由于这是一种传统的网站,它不太可能。那么,它还能是什么?我一度认为“Java版本”。不太可能,但或许值得一试。

As it is, I can get the content from previously error-throwing sites, if I compile my code with SDK 1.6.0_25. Newer versions gives me problems: 1.7.0_51, and 1.8.0.

如果我用SDK 1.6.0_25编译我的代码,就可以从以前的错误抛出站点获得内容。更新的版本给了我一些问题:1.7.0_51和1.8.0。

I have boiled it down to the smallest piece possible, if effect reproducing the one-liner initially posted by “Yankee” above. I have used the same line, including the same URL.

我已经把它浓缩成最小的部分,如果效果再现了上面的“洋基”最初发布的一艘客轮。我使用了相同的行,包括相同的URL。

Compiling with SDK 1.6 it works.

使用SDK 1.6进行编译。

I am not sufficiently skilled in Java and SSL to understand the root issue behind this. But, someone ought to be able to put the code side by side, and track it down..

我在Java和SSL方面不够熟练,无法理解这背后的根本问题。但是,应该有人能够将代码并排放在一起,并跟踪它。

This may save someone a few wasted hours.

这可能会节省几个小时。

#4


0  

It looks like you are not using java 1.8

看起来您没有使用java 1.8。

In Java 1.8 the default TLS protocol version is v1.2, whereas in Java 1.6,1.7 default is TLS1.0. As you can see in logs ClientHello, TLSv1.2 it means you are either using java 1.6 or 1.7 now you can either switch to 1.8 or Just add

在Java 1.8中,默认的TLS协议版本是v1.2,而在Java 1.6中,默认是TLS1.0。正如您在日志ClientHello中看到的,TLSv1.2表示您使用的是java 1.6或1.7,现在您可以切换到1.8或只添加。

static { System.setProperty("https.protocols", "TLSv1.2"); }

静态{ System.setProperty(“https。协议”、“TLSv1.2”);}

in your application class before main class keeping you current java version
.. hope this helps !!

在主类之前的应用程序类中,保持当前的java版本。希望这有助于! !

#1


7  

I see from the debug that Java does a TLS1.2 handshake instead of the more common SSLv23 handshake:

我从调试中看到,Java做了TLS1.2握手,而不是更常见的SSLv23握手:

main, WRITE: TLSv1.2 Handshake, length = 225
[Raw write]: length = 230
0000: 16 03 03 00
         ^^^^^ - TLS1.2 (SSL3.3)

The server itself can do only TLS1.0 and fails to just announce this older version. I'm not familiar with Java, but you either need set the protocol version to TLSv1 or SSLv23 to speak with this server.

服务器本身只能执行TLS1.0,并且不能只宣布这个旧版本。我不熟悉Java,但是您可能需要将协议版本设置为TLSv1或SSLv23来与此服务器对话。

The following code would set only TLSv1 with Apache HttpClient:

下面的代码将只设置与Apache HttpClient的TLSv1:

HttpClientBuilder
  .create()
  .setSslcontext(SSLContexts.custom().useProtocol("TLSv1").build())
  .build()
  .execute(new HttpGet("https://hubic.com"));

EDIT to include question from comment:

编辑以包括评论的问题:

If you say that the server "fails to just announce this older version", does that mean that the server is misconfigured? In this case, why don't Firefox&Chromium have any problems?

如果您说服务器“不只是宣布这个旧版本”,这是否意味着服务器被错误配置了?在这种情况下,为什么Firefox&Chromium没有任何问题呢?

If the client announces TLS1.2 in the ClientHello and the server can do only TLS1.0 it should announce this, i.e. reply with TLS1.0. The client can then close the connection if TLS1.0 is not good enough or continue with TLS1.0. But, in this case the server just told the client that it does not like this version and closed the connection. Firefox and others instead do a SSLv23 announcement, where they do a TLS1.0 handshake but also announce the best protocol version they support. This usually works good for older servers starting from SSL3.0 but also for newer servers.

如果客户在ClientHello中宣布TLS1.2,而服务器只能执行TLS1.0,则应该声明这个,即使用TLS1.0进行回复。如果TLS1.0不够好或继续使用TLS1.0,客户端可以关闭连接。但是,在这种情况下,服务器只是告诉客户机它不喜欢这个版本并关闭连接。Firefox和其他浏览器则采用SSLv23声明,在那里他们进行了TLS1.0的握手,同时也宣布了他们支持的最好的协议版本。这通常适用于从SSL3.0开始的旧服务器,但也适用于较新的服务器。

You can check the behavior of the server with a recent Perl/IO::Socket::SSL and this script.

您可以使用最近的Perl/IO::Socket::SSL和这个脚本检查服务器的行为。

$ perl analyze-ssl.pl hubic.com
-- hubic.com port 443
 * maximum SSL version  : TLSv1 (SSLv23)
 * supported SSL versions with handshake used and preferred cipher(s):
   * handshake protocols ciphers
   * SSLv23    TLSv1     AES256-SHA
   * TLSv1_2   FAILED: SSL connect attempt failed error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number
   * TLSv1_1   FAILED: SSL connect attempt failed error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number
   * TLSv1     TLSv1     AES256-SHA
   * SSLv3     FAILED: SSL connect attempt failed because of handshake problems error:1409442E:SSL routines:SSL3_READ_BYTES:tlsv1 alert protocol version

Here you can see, that the hosts supports SSLv23 and TLSv1 handshakes, but not the used TLSv1_2 handshake.

在这里您可以看到,主机支持SSLv23和TLSv1握手,而不是使用的TLSv1_2握手。

#2


1  

HttpClient can take an SSLContext for its SSLConnectionSocketFactory.

HttpClient可以为它的SSLConnectionSocketFactory获取SSLContext。

You can set the appropriate TLS version in the properties for the SSLContext with the getInstance static method.

您可以使用getInstance静态方法在SSLContext的属性中设置适当的TLS版本。

Something like SSLContext context = SSLContext.getInstance("TLSv1");

类似SSLContext上下文= SSLContext. getinstance(“TLSv1”);

If you need to force just one protocol (as getInstance can return one that supports multiple protocols), you can use the setEnabledProtocols method (which takes a String[]) on the context you retrieved using getInstance.

如果您只需要强制一个协议(因为getInstance可以返回一个支持多个协议的协议),那么您可以使用setenabledprotocol方法(它接受一个字符串[])在您使用getInstance检索的上下文中。

#3


1  

I have also come across this issue. Certain sites are not accessible, throwing the mysterious: javax.net.ssl.SSLException: Received fatal alert: protocol_version

我也遇到过这个问题。某些站点是不可访问的,抛出了神秘的:javax.net. sslxception:收到了致命警告:协议版本。

I have tried to mend it, following some of the hints given here, but without success. At one point the usual thought “it used to work before..”, really started nagging me.

我试着去修补它,遵循了这里给出的一些提示,但没有成功。在某一点上,通常的想法是“以前工作过……”,真的开始唠叨我了。

Initially I had assumed something had changed in the site I tried to connect to. However, as this is a legacy kind of site, it wasn’t so likely. So, what else could it be..? At one point I thought “Java version”. Unlikely, but maybe worth a try.

起初,我以为我尝试连接的网站发生了一些变化。然而,由于这是一种传统的网站,它不太可能。那么,它还能是什么?我一度认为“Java版本”。不太可能,但或许值得一试。

As it is, I can get the content from previously error-throwing sites, if I compile my code with SDK 1.6.0_25. Newer versions gives me problems: 1.7.0_51, and 1.8.0.

如果我用SDK 1.6.0_25编译我的代码,就可以从以前的错误抛出站点获得内容。更新的版本给了我一些问题:1.7.0_51和1.8.0。

I have boiled it down to the smallest piece possible, if effect reproducing the one-liner initially posted by “Yankee” above. I have used the same line, including the same URL.

我已经把它浓缩成最小的部分,如果效果再现了上面的“洋基”最初发布的一艘客轮。我使用了相同的行,包括相同的URL。

Compiling with SDK 1.6 it works.

使用SDK 1.6进行编译。

I am not sufficiently skilled in Java and SSL to understand the root issue behind this. But, someone ought to be able to put the code side by side, and track it down..

我在Java和SSL方面不够熟练,无法理解这背后的根本问题。但是,应该有人能够将代码并排放在一起,并跟踪它。

This may save someone a few wasted hours.

这可能会节省几个小时。

#4


0  

It looks like you are not using java 1.8

看起来您没有使用java 1.8。

In Java 1.8 the default TLS protocol version is v1.2, whereas in Java 1.6,1.7 default is TLS1.0. As you can see in logs ClientHello, TLSv1.2 it means you are either using java 1.6 or 1.7 now you can either switch to 1.8 or Just add

在Java 1.8中,默认的TLS协议版本是v1.2,而在Java 1.6中,默认是TLS1.0。正如您在日志ClientHello中看到的,TLSv1.2表示您使用的是java 1.6或1.7,现在您可以切换到1.8或只添加。

static { System.setProperty("https.protocols", "TLSv1.2"); }

静态{ System.setProperty(“https。协议”、“TLSv1.2”);}

in your application class before main class keeping you current java version
.. hope this helps !!

在主类之前的应用程序类中,保持当前的java版本。希望这有助于! !