HttpClient支持多种TLS协议 [英] HttpClient supporting multiple TLS protocols

查看:1138
本文介绍了HttpClient支持多种TLS协议的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在编写一个必须使用HTTPS与几台服务器通信的应用。
它需要与AWS(使用AWS库)以及我们使用TLS 1.2的一些内部服务进行通信。

We're writing an app that must communicate with a few servers using HTTPS. It needs to communicate with AWS (using the AWS libraries) and also with some of our internal services that use TLS 1.2.

我开始通过更改我的HttpClient使用TLS 1.2 SSLContext:

I started off by changing my HttpClient to use a TLS 1.2 SSLContext:

public static SchemeRegistry buildSchemeRegistry() throws Exception {
    final SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
    sslContext.init(createKeyManager(), createTrustManager(), new SecureRandom());
    final SchemeRegistry schemeRegistry = new SchemeRegistry();
    schemeRegistry.register(new Scheme("https", 443, new SSLSocketFactory(sslContext)));
    return schemeRegistry;
}

并将此SchemeRegistry注入DefaultHttpClient对象(通过spring),但这样做我从AWS收到错误,因此我假设(我可能错了)AWS不支持TLS 1.2(如果我只使用正常的DefaultHttpClient,我不会收到此消息):

and injecting this SchemeRegistry into the DefaultHttpClient object (via spring), but doing that I get errors from AWS and so I assume (I may be wrong) that AWS doesn't support TLS 1.2 (I don't get this message if I just use the normal DefaultHttpClient):

AmazonServiceException: Status Code: 403, AWS Service: AmazonSimpleDB, AWS Request ID: 5d91d65f-7158-91b6-431d-56e1c76a844c, AWS Error Code: InvalidClientTokenId, AWS Error Message: The AWS Access Key Id you provided does not exist in our records.

如果我尝试在spring中定义两个HttpClient,一个使用TLS 1.2,一个是默认情况下,我得到以下错误,我认为这意味着Spring不喜欢实例化和自动装配两个HttpClient对象:

If I try to have two HttpClients defined in spring, one that uses TLS 1.2 and one that is the default, I get the following error, which I assume means that Spring doesn't like instantiating and autowiring two HttpClient objects:

SEVERE: Servlet /my-refsvc threw load() exception
java.lang.NullPointerException
at com.company.project.refsvc.base.HttpsClientFactory.<clinit>(BentoHttpsClientFactory.java:25)
...
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1031)
at 
...
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)

我没有使用过HTTPS在java中你能得到一些好意见吗?
1)我如何让Spring允许两个HttpClient对象,一个连接到AWS东西bean,另一个连接到其他bean以访问TLS1.2服务
2)或者是否可以更改一个HttpClient对象以便能够尝试TLS1.2(通过SSLContext,或者SchemeRegistry或其他东西),如果失败则尝试TLS1.1或1.0?
3)如果两者都有可能,那么更好的做法是什么?

I haven't used HTTPS much in java so could you kind people give me some advice please? 1) How would I get Spring to allow two HttpClient objects and for one to be wired to the AWS stuff beans and the other to be wired to the other beans for accessing the TLS1.2 services 2) Or is it possible to change the one HttpClient object to be able to try TLS1.2 (via SSLContext, or the SchemeRegistry or something) and if that fails then try TLS1.1 or 1.0? 3) If both are possible, what would be the 'better' way of doing it?

推荐答案

TLS有内置机制,用于协商使用哪个版本的协议。来自 RFC 5246(附录E)

TLS has an in-built mechanism to negotiate which version of the protocol is to be used. From RFC 5246 (Appendix E):


TLS版本1.0,1.1和1.2,以及SSL 3.0非常相似,
使用兼容的ClientHello消息;因此,支持所有这些
相对容易。同样,只要ClientHello
格式保持兼容,服务器就可以轻松处理客户端
尝试使用未来版本的TLS,并且客户端支持服务器中可用的最高
协议版本。

TLS versions 1.0, 1.1, and 1.2, and SSL 3.0 are very similar, and use compatible ClientHello messages; thus, supporting all of them is relatively easy. Similarly, servers can easily handle clients trying to use future versions of TLS as long as the ClientHello format remains compatible, and the client supports the highest protocol version available in the server.

希望与这些旧服务器进行协商的TLS 1.2客户
将发送一个普通的TLS 1.2 ClientHello,包含{3,3}(TLS
1.2) )在ClientHello.client_version中。如果服务器不支持此版本,它将使用包含
旧版本号的ServerHello进行响应。如果客户同意使用此版本,
协商将根据协商的
协议进行。

A TLS 1.2 client who wishes to negotiate with such older servers will send a normal TLS 1.2 ClientHello, containing { 3, 3 } (TLS 1.2) in ClientHello.client_version. If the server does not support this version, it will respond with a ServerHello containing an older version number. If the client agrees to use this version, the negotiation will proceed as appropriate for the negotiated protocol.

此外,更改 SSLContext.getInstance(...)中的版本号只会更改默认启用的协议。使用 SSLSocket.setEnabledProtocols(...) (参见这个问题)。我不确定你正在使用的其他库,但它可能会在某处设置启用的协议。

In addition, changing the version number in SSLContext.getInstance(...) only changes which protocols are enabled by default. Setting the actual protocol versions is done with SSLSocket.setEnabledProtocols(...) (see this question). I'm not sure about the rest of the libraries you're using, but it's possible that it sets the enabled protocols somewhere.

有几种可能性:


  • 你在 createKeyManager()中所做的事情与默认值不同行为。如果服务使用的是客户端证书身份验证,则配置错误肯定会导致403错误。

  • What you're doing in your createKeyManager() differs from the default behaviour. If the service is using client-certificate authentication, bad configuration there would certainly lead to a 403 error.

(不太可能,我猜,但很难说没有看到 createKeyManager() createTrustManager())。您使用的服务器可能与TLS 1.2和版本协商机制不兼容。 sun.security.ssl.SSLContextImpl 中有此评论:

(Less likely, I guess, but hard to say without seeing your createKeyManager() and createTrustManager()). Perhaps the server you're using isn't compatible with TLS 1.2 and the version negotiation mechanism. There is this comment in sun.security.ssl.SSLContextImpl:


SSL / TLS协议指定了前向兼容性和版本
回滚攻击保护,但是,许多SSL / TLS服务器
供应商没有正确实现这些方面,以及一些当前的
SSL / TLS服务器可能拒绝与TLS 1.1或更高版本的客户交谈。

SSL/TLS protocols specify the forward compatibility and version roll-back attack protections, however, a number of SSL/TLS server vendors did not implement these aspects properly, and some current SSL/TLS servers may refuse to talk to a TLS 1.1 or later client.


这篇关于HttpClient支持多种TLS协议的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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