禁用 HttpsURLConnection 的证书验证仍然得到 javax.net.ssl.SSLHandshakeException:收到致命警报:handshake_failure
Disabled certificate validation for HttpsURLConnection still getting javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
我正在编写一些代码,可以将 HTTP GET/POST 请求发送到目标服务器。当应用程序尝试建立与安全服务器 (https) 的连接时,问题就出现了。为此,我使用了 HttpsURLConnection,如下所示:
url = new URL("https://www.sendspace.com/");
String input, htmlResponse = "";
HttpsURLConnection con;
con = (HttpsURLConnection)url.openConnection();
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
while ((input = br.readLine()) != null){
htmlResponse += input;
}
br.close();
但是,它显示了以下错误:
javax.net.ssl.SSLHandshakeException: Received fatal alert:
handshake_failure
因此,我把上面的代码改成这样:
url = new URL("https://www.sendspace.com/");
String input, htmlResponse = "";
SSLUtilities.trustAllHostnames();
SSLUtilities.trustAllHttpsCertificates();
HttpsURLConnection con;
// code below has not been changed
其中使用了 SSLUtilities.java。
但是,我注意到这样做没有任何效果,因为我仍然再次收到完全相同的错误:
javax.net.ssl.SSLHandshakeException: Received fatal alert:
handshake_failure
同样,我也尝试使用不同的方法,其中涉及在启动 HttpsURLConnection 之前使用此行来使用 SSLCertificateValidation.java:
SSLCertificateValidation.disable();
甚至使用它返回的错误与之前解释的完全相同。我想确切地知道为什么这种方法不起作用,我怎样才能避免这个错误?
请注意以下事项:
不用说,我已经对这个问题进行了广泛的搜索,并且已经花了相当多的时间,尝试了不同的建议和代码示例,但都无济于事。我知道这个错误在问题中出现了很多,但我没有找到与我自己相关的已经存在的具体答案。
我知道并理解因禁用证书验证而出现的安全问题。但是,由于此应用程序会连接到 100 到 200 台不同的服务器(根据需要),因此在每个服务器的基础上管理证书是不可行的。因此,除非有人可以说明 (a) 检索、(b) 存储和 (c) 在每个服务器的基础上(在运行时)使用正确证书的方法,否则所有这些都必须以编程方式完成,无需任何手动工作,建议 "clean" 方法不是解决这种情况的方法。
谢谢。
握手失败不是证书验证错误,因此您不能通过忽略证书错误来修复它(无论如何这是一个坏主意)。 SSLLabs 页面更清楚地说明了问题的真正原因:
Java 8u31 Protocol or cipher suite mismatch
如果您查看服务器支持的密码(同样在 SSLLabs 报告中),您可以看到所有密码都包含密钥大小为 256 的 AES。但在 documentation about supported key sizes 中指出,因为由于出口限制,AES 支持的最大密钥大小为 128。这意味着您的客户端仅提供 AES128 密码,而服务器仅接受 AES256 密码,即没有共享密码。
要解决此问题,您必须按照参考文档中的说明进行操作:
If stronger algorithms are needed (for example, AES with 256-bit keys), the JCE Unlimited Strength Jurisdiction Policy Files must be obtained and installed in the JDK/JRE.
我正在编写一些代码,可以将 HTTP GET/POST 请求发送到目标服务器。当应用程序尝试建立与安全服务器 (https) 的连接时,问题就出现了。为此,我使用了 HttpsURLConnection,如下所示:
url = new URL("https://www.sendspace.com/");
String input, htmlResponse = "";
HttpsURLConnection con;
con = (HttpsURLConnection)url.openConnection();
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
while ((input = br.readLine()) != null){
htmlResponse += input;
}
br.close();
但是,它显示了以下错误:
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
因此,我把上面的代码改成这样:
url = new URL("https://www.sendspace.com/");
String input, htmlResponse = "";
SSLUtilities.trustAllHostnames();
SSLUtilities.trustAllHttpsCertificates();
HttpsURLConnection con;
// code below has not been changed
其中使用了 SSLUtilities.java。 但是,我注意到这样做没有任何效果,因为我仍然再次收到完全相同的错误:
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
同样,我也尝试使用不同的方法,其中涉及在启动 HttpsURLConnection 之前使用此行来使用 SSLCertificateValidation.java:
SSLCertificateValidation.disable();
甚至使用它返回的错误与之前解释的完全相同。我想确切地知道为什么这种方法不起作用,我怎样才能避免这个错误?
请注意以下事项:
不用说,我已经对这个问题进行了广泛的搜索,并且已经花了相当多的时间,尝试了不同的建议和代码示例,但都无济于事。我知道这个错误在问题中出现了很多,但我没有找到与我自己相关的已经存在的具体答案。
我知道并理解因禁用证书验证而出现的安全问题。但是,由于此应用程序会连接到 100 到 200 台不同的服务器(根据需要),因此在每个服务器的基础上管理证书是不可行的。因此,除非有人可以说明 (a) 检索、(b) 存储和 (c) 在每个服务器的基础上(在运行时)使用正确证书的方法,否则所有这些都必须以编程方式完成,无需任何手动工作,建议 "clean" 方法不是解决这种情况的方法。
谢谢。
握手失败不是证书验证错误,因此您不能通过忽略证书错误来修复它(无论如何这是一个坏主意)。 SSLLabs 页面更清楚地说明了问题的真正原因:
Java 8u31 Protocol or cipher suite mismatch
如果您查看服务器支持的密码(同样在 SSLLabs 报告中),您可以看到所有密码都包含密钥大小为 256 的 AES。但在 documentation about supported key sizes 中指出,因为由于出口限制,AES 支持的最大密钥大小为 128。这意味着您的客户端仅提供 AES128 密码,而服务器仅接受 AES256 密码,即没有共享密码。
要解决此问题,您必须按照参考文档中的说明进行操作:
If stronger algorithms are needed (for example, AES with 256-bit keys), the JCE Unlimited Strength Jurisdiction Policy Files must be obtained and installed in the JDK/JRE.