【问题标题】:How to enforce TLS1.2 to Rest client using Rest Template如何使用 Rest Template 强制 TLS1.2 到 Rest 客户端
【发布时间】:2017-01-02 20:17:52
【问题描述】:

我正在使用 Spring3.0 restTemplate 通过调用 post 方法来使用 json webservice。

        MultiValueMap<String, String> headers = new LinkedMultiValueMap<String, String>();
        headers.add("Content-Type", MediaType.APPLICATION_JSON_VALUE);      
        HttpEntity<Object> entity = new HttpEntity<Object>(requestAsString, headers);
        postForObject = restTemplate.postForObject(url, entity, responseClass );

我们的应用程序部署在 WAS 服务器中,并尝试通过使用 TLS1.0 创建套接字连接来连接生产者。但是,现在 producer 只支持 TLS1.1 和 TLS1.2。

如何强制 restTempate 使用 TLS1.1 或 TLS 1.2。

通常对于 apache httpclient 代码,创建自定义 ProtocolSocketFactory 并覆盖 createSocket 方法。但是,在 RestTemplate 的情况下,如何实现。

【问题讨论】:

  • TLS 2.0 不存在,因此很难“支持”。
  • 感谢指出,有问题已更正

标签: java spring resttemplate tls1.2


【解决方案1】:

使用 Spring > 3.1:

import javax.net.ssl.SSLContext;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

SSLContext context = SSLContext.getInstance("TLSv1.2");
context.init(null, null, null);

CloseableHttpClient httpClient = HttpClientBuilder.create().setSSLContext(context)
    .build();
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);
RestTemplate restTemplate = new RestTemplate(factory);
.....

【讨论】:

  • 我如何使用 Spring 3.0.x 做到这一点?
  • @membersound 接受的答案不是关于更好的答案,而是关于什么适用于 OP,而且无论如何问题都是关于 spring 3.0 的。我也很欣赏这个答案,并赞成
  • @abhishekhp,你有解决办法吗?
  • 完全同意该解决方案,但对context.init(null, null, null) 为何会有所帮助的见解很少。我的意思是,如果它们是可选的,为什么不重载并提供一个不需要 args 的呢?
  • 关于 context.init,文档说:前两个参数中的任何一个都可能为空,在这种情况下,将搜索已安装的安全提供程序以查找相应工厂的最高优先级实现。同样,安全随机参数可能为空,在这种情况下将使用默认实现。
【解决方案2】:

您可以将 RestTemplate 配置为使用自定义 ClientHttpRequestFactory。特别是(因为您使用的是 Spring 3.0),有一个 CommonsClientHttpRequestFactory。这将使您能够详细配置公共 HTTP,并且您的 RestTemplate 将使用它来执行其请求。

请注意,实际的实现类在 Spring 的更高版本中发生了变化(如果您仍在使用 3.0,那么您真的应该考虑更新)。从 3.1 开始,实现类被称为HttpComponentsClientHttpRequestFactory

【讨论】:

  • 嗨@mar​​thursson,如果在春季3使用CommonsClientHttpRequestFactory,意味着httpClient必须使用org.apache.commons.httpclient.HttpClient?或者我们可以使用org.apache.http.impl.client.DefaultHttpClient
【解决方案3】:

@abhishekhp 如果您的问题仍然存在。

    RestTemplate restTemplate = new RestTemplate();
    DefaultHttpClient httpClient = new DefaultHttpClient();
    // We're going to try and load and enable TLS version 1.2 standard communication context from JSSE Providers
    // This is enabled only for download media Mirakl as some merchants don't accept communication with TLS versions prior to 1.1
    try {
        SSLContext context;
        context = SSLContext.getInstance("TLSv1.2");
        context.init(null, null, null);

        SSLSocketFactory ssf = new SSLSocketFactory(context);
        ClientConnectionManager ccm = httpClient.getConnectionManager();
        SchemeRegistry sr = ccm.getSchemeRegistry();
        sr.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
        sr.register(new Scheme("https", 443, ssf));

    } catch (NoSuchAlgorithmException | KeyManagementException e) {
        LOGGER.warn("Could not load the TLS version 1.2 due to => ", e);
    }

    restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient));

【讨论】:

  • HttpComponentsClientHttpRequestFactory 适用于 spring 3.0.x?
【解决方案4】:

如果您想设置多个有效的 TLS 版本,请使用 SSLConnectionSocketFactory。例如,如果您想支持 TLSv1.2 和 TLSv1.3:

public HttpClient getHttpClient() {
    final var sslContext = SSLContext.getDefault();
    // TLSv1.2 or TLSv1.3
    final var sslConnectionSocketFactory =
        new SSLConnectionSocketFactory(sslContext, new String[]{"TLSv1.2","TLSv1.3"},
            null, javax.net.ssl.HttpsURLConnection.getDefaultHostnameVerifier());

    return  HttpClients.custom().setSSLSocketFactory(sslConnectionSocketFactory).build();
}

并将其与RestTemplate 结合起来,如下所示:

@Bean
public RestTemplate restTemplate() {
    final var factory = new HttpComponentsClientHttpRequestFactory(getHttpClient());
    return new RestTemplate(factory);
}

【讨论】:

  • 这在 Rest 模板中是如何使用的?
  • @IcedD​​ante 我更新了答案
猜你喜欢
  • 2020-06-11
  • 2013-01-17
  • 2015-07-23
  • 2011-02-02
  • 1970-01-01
  • 2015-04-23
  • 1970-01-01
  • 1970-01-01
  • 2013-07-07
相关资源
最近更新 更多