如何强制 Commons HTTPClient 3.1 仅将 TLS 1.2 用于 HTTPS?

2022-09-02 01:23:51

我希望强制Apache Commons HTTP-Client(版本3.1)使用TLS 1.2作为HTTPS的唯一协议。

这是由于服务器应该已升级到TLS 1.2并且不再接受任何较旧的协议(导致返回“连接重置”)。

对于进一步的上下文,可能无关紧要,HTTP客户端与Axis2一起使用来制作SOAP;用于设置HttpClient的一些代码如下:

MultiThreadedHttpConnectionManager connMgr = new MultiThreadedHttpConnectionManager();
this.httpClient = new HttpClient(connMgr);

// initialize HttpClient parameters
HttpClientParams hcParams = this.httpClient.getParams();

// Maximum time to wait to receive connection from pool
hcParams.setConnectionManagerTimeout(this.maxWait);
hcParams.setSoTimeout(this.timeout);
hcParams.setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler(this.retryCount, false));

// Initialize global Connection manager parameters
HttpConnectionManagerParams cmParams = connMgr.getParams();
cmParams.setDefaultMaxConnectionsPerHost(this.maxActive);
cmParams.setStaleCheckingEnabled(this.checkStaleConnections);
cmParams.setConnectionTimeout(this.timeout);

非常感谢您的帮助!


答案 1

太可惜了,没有人回答;我能够做到这一点,首先你写了一个CustomHttpSocketFactory,然后你做了:

String scheme = "https";
Protocol baseHttps = Protocol.getProtocol(scheme);
int defaultPort = baseHttps.getDefaultPort();

ProtocolSocketFactory baseFactory = baseHttps.getSocketFactory();
ProtocolSocketFactory customFactory = new CustomHttpsSocketFactory(baseFactory);

Protocol customHttps = new Protocol(scheme, customFactory, defaultPort);
Protocol.registerProtocol(scheme, customHttps); 

在这里可以找到一个示例自定义套接字工厂代码,但我做了:

public class CustomHttpsSocketFactory implements SecureProtocolSocketFactory
{

   private final SecureProtocolSocketFactory base;

   public CustomHttpsSocketFactory(ProtocolSocketFactory base)
   {
      if(base == null || !(base instanceof SecureProtocolSocketFactory)) throw new IllegalArgumentException();
      this.base = (SecureProtocolSocketFactory) base;
   }

   private Socket acceptOnlyTLS12(Socket socket)
   {
      if(!(socket instanceof SSLSocket)) return socket;
      SSLSocket sslSocket = (SSLSocket) socket;
      sslSocket.setEnabledProtocols(new String[]{"TLSv1.2" });
      return sslSocket;
   }

   @Override
   public Socket createSocket(String host, int port) throws IOException
   {
      return acceptOnlyTLS12(base.createSocket(host, port));
   }
   @Override
   public Socket createSocket(String host, int port, InetAddress localAddress, int localPort) throws IOException
   {
      return acceptOnlyTLS12(base.createSocket(host, port, localAddress, localPort));
   }
   @Override
   public Socket createSocket(String host, int port, InetAddress localAddress, int localPort, HttpConnectionParams params) throws IOException
   {
      return acceptOnlyTLS12(base.createSocket(host, port, localAddress, localPort, params));
   }
   @Override
   public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException
   {
      return acceptOnlyTLS12(base.createSocket(socket, host, port, autoClose));
   }

}

答案 2

代码中需要一个套接字引用。然后,您可以像这样在其上设置启用的协议:

if (socket != null && (socket instanceof SSLSocket)) {
    ((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.2"});
}