HttpClient支持多种TLS协议
我们正在编写一个必须使用HTTPS与几台服务器通信的应用程序。 它需要与AWS(使用AWS库)以及使用TLS 1.2的一些内部服务进行通信。
我开始通过更改我的HttpClient来使用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):
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不喜欢实例化并自动assembly两个HttpClient对象:
SEVERE: Servlet /my-refsvc threw load() exception java.lang.NullPointerException at com.company.project.refsvc.base.HttpsClientFactory.(BentoHttpsClientFactory.java:25) ... org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1031) at ... org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
我没有在Java中使用过多的HTTPS,所以请问有什么人给我一些建议吗? 1)我如何让Spring允许两个HttpClient对象,一个连接到AWS东西bean,另一个连接到其他bean以访问TLS1.2服务2)或者是否可以更改一个HttpClient对象能够尝试TLS1.2(通过SSLContext,或SchemeRegistry或其他东西),如果失败,那么尝试TLS1.1或1.0? 3)如果两者都有可能,那么“更好”的做法是什么?
TLS有一个内置机制来协商使用哪个版本的协议。 来自RFC 5246(附录E) :
TLS版本1.0,1.1和1.2以及SSL 3.0非常相似,并使用兼容的ClientHello消息; 因此,支持所有这些相对容易。 同样,只要ClientHello格式保持兼容,服务器就可以轻松处理尝试使用未来版本TLS的客户端,并且客户端支持服务器中可用的最高协议版本。
希望与这些旧服务器协商的TLS 1.2客户端将在ClientHello.client_version中发送包含{3,3}(TLS 1.2)的普通TLS 1.2 ClientHello。 如果服务器不支持此版本,它将使用包含旧版本号的ServerHello进行响应。 如果客户同意使用此版本,则协商将根据协商协议进行。
此外,更改SSLContext.getInstance(...)
的版本号仅会更改默认启用的协议。 使用SSLSocket.setEnabledProtocols(...)
设置实际协议版本(请参阅此问题 )。 我不确定你正在使用的其他库,但它可能会在某处设置启用的协议。
有几种可能性:
-
您在
createKeyManager()
所做的事情与默认行为不同。 如果服务使用客户端证书身份validation,配置错误肯定会导致403错误。 -
(不太可能,我猜,但很难说没有看到你的
createKeyManager()
和createTrustManager()
)。 您使用的服务器可能与TLS 1.2和版本协商机制不兼容。sun.security.ssl.SSLContextImpl
有此评论:SSL / TLS协议指定了前向兼容性和版本回滚攻击保护,但是,许多SSL / TLS服务器供应商没有正确实现这些方面,并且一些当前的SSL / TLS服务器可能拒绝与TLS 1.1或更高版本通信客户。
- 如何强制Commons HTTPClient 3.1仅对HTTPS使用TLS 1.2?
- 如何配置HTTPClient以对SOCKS代理进行身份validation?
- 在不更改代码的情况下,如何强制httpClient通过环境变量或JVM参数使用代理
- 从Commons HttpClient迁移到HttpComponents Client
- 使用Apache的HTTP客户端时,将HTTP响应作为String的推荐方法是什么?
- HttpClient 4.2,基本身份validation和AuthScope
- 使用Apache commons HttpClient时,如何覆盖请求中的“Host”头
- Java – 将OutputStream上传为HTTP文件上载
- Apache HttpClient 4和JavaScript