当前位置: 首页 > 知识库问答 >
问题:

如何强制Commons HTTPClient 3.1仅对HTTPS使用TLS 1.2?

蒯宇定
2023-03-14

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

这是因为服务器应该升级到TLS 1.2,不再接受任何旧协议(导致返回“连接重置”)。

对于进一步的上下文,可能不相关,HTTP-Client与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);

非常感谢你的帮助!

共有3个答案

罗新
2023-03-14

这取决于您编写客户机的方式以及使用的JRE版本:

如果您使用JRE8(除非您已经替换了JRE8附带的默认SunJSSE),系统属性jdk.tls.client.protocols。默认情况下,您在这里提到的任何内容都将用于所有客户端通信

如果使用HttpsURLConnection对象进行客户端连接,则可以使用系统属性“https.protocols”。这将适用于所有JRE版本,而不仅仅是JRE8。

如果没有为TLS客户机指定任何内容,请在JRE8、TLSv1、v1中指定。1和v1。2已启用,因此它将与支持任何一个版本的服务器一起工作。然而,在JRE7中,默认情况下仅启用TLSv1。

在代码中,你总是可以覆盖默认值或你通过系统属性传递的内容。你在代码中设置的内容将具有更高的优先级。要在代码中重写。。。

1)如果你使用的是原始套接字和SSLEngine,你可以设置协议和密码在SSLEngine(sslEngine.set加密协议(...)

2)如果你使用SSLSocket,你可以在SSLSocket中设置协议和密码(sslSocket.set加密协议(...)

您还可以获得启用了所需协议的SSLContext,并将其用于您使用的任何SSL组件。SSLContext。getInstance(“TLSvx.x”)。请注意,默认情况下,它将返回一个上下文,其中包含TLSvx使用的所有协议。x已启用。如果您配置了“jdk.tls.client.protocols”,这将返回启用了这些协议的上下文。

在代码中硬编码协议不是一个好主意。我们经常会遇到某些客户想要特定的版本,要么是因为他们使用旧的服务器,要么是因为在一些TLS版本中遇到了一些严重的漏洞。要么通过系统属性设置它,要么即使您在sslocket或sslEngine中显式设置,也要从某个conf文件中读取它。

另请参考:

https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html

http://docs.oracle.com/javase/8/docs/technotes/guides/security/SunProviders.html

庞乐池
2023-03-14

您需要在代码中使用Socket引用。然后您可以像这样设置启用的协议:

if (socket != null && (socket instanceof SSLSocket)) {
    ((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.2"});
}
呼延钱明
2023-03-14

太糟糕了,没有人回答;我能够做到这一点,首先你写一个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));
   }

}
 类似资料:
  • 问题内容: 我希望强制 Apache Commons HTTP-Client (版本 3.1 )将 TLS 1.2 用作HTTPS 的 唯一 协议。 这是由于服务器应该升级到TLS 1.2,并且不再接受任何较旧的协议(导致返回“连接重置”)。 对于进一步的上下文(可能无关紧要),HTTP客户端与Axis2一起使用来创建SOAP;下面是用于设置HttpClient的一些代码: 非常感谢您的帮助! 问

  • 问题内容: 我正在尝试为Express.js创建一个中间件,以将所有非安全(端口80)通信重定向到安全SSL端口(443)。不幸的是,Express.js请求中没有任何信息可让您确定该请求是否来自http或https。 一种解决方案是重定向 每个 请求,但这不是我的选择。 笔记: 没有可能用Apache或其他东西来处理它。它 必须 在节点中完成。 应用程序中只能启动 一台 服务器。 您将如何解决?

  • 我似乎不能强迫https在弹性Beanstalk的自由使用层上。 关于如何在amazon elastic beanstalk上强制https而又不通过健康检查,我尝试了以下建议 使用此Apache重写规则 当我这样做时,http请求不会像我想的那样被重定向到https。相反,http页会正常加载。我也尝试使用X-Forwarded-Port报头,得到了同样的结果。 我也试过下面的重写规则 而此规则

  • 问题内容: 如何使用PHP中特定的.htaccess和mod_rewrite页面强制使用SSL / https。 问题答案: 对于Apache,您可以使用强制SSL : 除非为当前连接启用了SSL上的HTTP(即HTTPS),否则该指令禁止访问。这在启用SSL的虚拟主机或目录中非常方便,可防止配置错误暴露应受保护的内容。使用此指令时,将拒绝所有未使用SSL的请求。 不过,这不会重定向到https。

  • 我一直在尝试为我的网站配置这个,但是做不到。 我以前有一个cond。htaccess对主域名强制www,对子域什么都不用,但是自从我得到了一个SSL,我遇到了一些问题。 这是一个通配符SSL。 我需要的是在主域上强制HTTPS://WWW,在子域上强制HTTPS://。 即:http://www.domain.com - 有什么规定吗?谢谢! 编辑 现在我用乔恩贴的 问题是,当我在主域上键入 HT

  • 问题内容: 有一个在Tomcat上运行的JDK7应用程序,它具有以下环境设置: 上面的设置可确保在进行API调用等操作时通过HTTPS连接时不使用TLS 1.0。 我们还使用org.springframework.mail.javamail。 JavaMailSenderImpl 类发送外发SMTP电子邮件,并使用以下道具: 问题是,当升级到TLS1.2时,与SMTP电子邮件服务器的连接失败。 j