【发布时间】:2019-03-28 22:52:04
【问题描述】:
我正在尝试对其他服务器实施基于 SSL 的 HTTPS 连接。
我需要提供所有协议(TLSv1.0、TLSv1.1、TLSv1.2、TLSv1.3),并且无论哪个可用或启用,它都应该能够自行协商该版本。
目前是这样的:
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, /*some certs*/, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
String webServicePath =" https://google.com" //suppose
URL url = new URL(webServicePath);
HttpsURLConnection httpsCon = (HttpsURLConnection) url.openConnection();
httpsCon.setRequestMethod("POST");
httpsCon.setRequestProperty("Content-Type", "application/json");
httpsCon.setRequestProperty("Content-Language", "en-US");
httpsCon.setUseCaches(false);
httpsCon.setDoInput(true);
httpsCon.setDoOutput(true);
httpsCon.setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
httpsCon.connect();
我想要类似:SSLContext.getInstance("TLSv1.0, TLSv1.1, TLSv1.2"); 但我不确定此方法是否需要多个参数。
我找到了解决方案:Dhttps.protocols=TLSv1.2,TLSv1.1,TLSv1” 在启动Java VM时,或者在代码中,等效的系统属性指令是“System.setProperty(“https.protocols” , “TLSv1.2,TLSv1.1,TLSv1”)”。
我想在我的代码中以编程方式执行此操作,但我不知道如何。
我读到客户端和服务器通过 HELLO 消息进行协商,直到他们同意双方支持的协议版本。为了实现这种协商,我必须在源代码中实现它吗?
【问题讨论】:
-
“我正在尝试实现基于 SSL 的 HTTPS”。第一个建议:不要再说 SSL。这已被 20 年前创建的 TLS 所取代。
-
“无论哪个可用或启用,它都应该能够自行协商该版本”阅读有关 TLS1.3 的 RFC8446 的长篇文章,其中包含有关如何与 1.3 服务器和旧客户端互操作的大量章节或相反。有许多细节需要正确实施。 “我读到客户端和服务器通过 HELLO 消息进行协商,直到他们同意双方支持的协议版本。”这在 TLS 握手中称为
ServerHello和ClientHello。所有这些都应该被你使用的 TLS 库抽象出来,从阅读它的文档开始。 -
@PatrickMevzek 感谢您的回复。实际上,我的代码正在访问 Web 服务,但不知道为什么我在 httpsCon.connect(); - java.lang.RuntimeException: javax.net.ssl 上遇到握手失败异常。 SSLHandshakeException:收到致命警报:handshake_failure。相同的代码在 PROD 上运行良好。首先我认为它的版本兼容性问题。