如何使用Apache HttpClient 4添加对已弃用的SSL密码套件的支持

时间:2016-06-17 16:05:53

标签: java ssl apache-httpclient-4.x tls1.2

问题

所以,我有一台我需要连接的服务器,它使用旧的,已弃用的证书。如果我尝试使用Apache HttpClient与其建立联系,我会获得SSLException: Received fatal alert: close_notify。客户端本身不需要可重用于其他服务器,但构建器代码必须能够。

我不太理想的解决方法

我通过设置回退TLS协议解决了这个问题,但它并不理想,因为它增加了另一个请求。必须有一个比这更优雅的方式:

URL url = new URL("https://...");
SSLContextBuilder sslContextBuilder = SSLContexts.custom();
try {
    url.openConnection().connect();
} catch (SSLException e) {
    sslContextBuilder.useProtocol("TLSv1");
}

我也尝试了

我还尝试创建自定义SSLConnectionSocketFactory,但如果TLSv1作为选项包含,则apache会忽略TLSv1.2

SSLConnectionSocketFactory sf = new SSLConnectionSocketFactory(
        SSLContext.getDefault(),
        new String[] { "TLSv1.2", "TLSv1" },
        null,
        SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);

反射

实质上,我认为基本问题是远程服务器使用不推荐使用的密码套件。我可以将我想要支持的所有密码套件传递到SSLConnectionSocketFactory,但是有很多,Sun已经隐藏了私有类背后的完整列表。

1 个答案:

答案 0 :(得分:1)

您可以通过删除$ JAVA_HOME / jre / lib / security / java.security中的jdk.tls.disabledAlgorithms来使用不推荐使用的密码套件(例如SSL_RSA_WITH_RC4_128_SHA)。

e.g。默认HttpClient访问的https://ex.qq.com/将返回Received fatal alert: handshake_failure。但是下面的代码可以工作:

public static void main(String[] args) throws Exception {
    HttpClientBuilder builder = HttpClientBuilder.create().
            setSSLSocketFactory(new SSLConnectionSocketFactory(SSLContext.getDefault(),
            new String[] {"TLSv1"}, new String[] {"SSL_RSA_WITH_RC4_128_SHA"}, new DefaultHostnameVerifier()));
    try (CloseableHttpClient client = builder.build()) {
        HttpGet get = new HttpGet("https://ex.qq.com/");
        System.out.println(client.execute(get).getStatusLine().getStatusCode());
    }
}

有关详细信息,请参阅此问题:Received fatal alert: handshake_failure through SSLHandshakeException