我正在研究一些将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:收到致命警报: 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:收到致命警报: handshake_failure
同样,我也尝试使用不同的方法,在开始HttpsURLConnection之前使用SSLCertificateValidation.java使用此行:
SSLCertificateValidation.disable();
甚至使用它返回与前面解释的完全相同的错误。我想知道为什么这种方法不起作用,我怎么可能绕过这个错误?
请注意以下事项:
不言而喻,我已经在这个问题上进行了广泛的搜索,并且已经花了相当多的时间,尝试了不同的建议和代码示例,但无济于事。我知道这个错误在问题中已经出现了很多,但我找不到与我自己有关的具体答案。
我了解并了解因禁用证书验证而导致的安全问题。但是,由于此应用程序将连接到100到200个不同的服务器(在需要时),因此无法按服务器管理证书。因此,除非有人能够陈述(a)检索,(b)存储和(c)基于每个服务器(在运行时)使用正确证书的方法,所有这些都必须以编程方式完成,无需任何手工工作,建议"清洁"这样做的方法不是这种情况的解决方案。
感谢。
答案 0 :(得分:3)
握手失败不是证书验证错误,因此您无法通过忽略证书错误来修复它(无论如何这都是一个坏主意)。 SSLLabs页面更清楚地说明了问题的真正原因:
Java 8u31 Protocol or cipher suite mismatch
如果查看服务器支持的密码(再次在SSLLabs报告中),您可以看到所有密码都包含密钥大小为256的AES。但在documentation about supported key sizes中,它表示由于导出限制AES支持的最大密钥大小为128.这意味着您的客户端仅提供AES128密码,而服务器只接受AES256密码,即没有共享密码。
要解决此问题,您必须按照参考文档中的说明进行操作:
如果需要更强大的算法(例如,使用256位密钥的AES),则必须获取JCE Unlimited Strength Jurisdiction Policy Files并将其安装在JDK / JRE中。