我的想法已经不多了,这就是我在这里寻求帮助的原因。我有一个通过HTTPS进行REST调用的小类。我正在进行某种抓取,并希望尽可能避免安装所有SSL证书。
代码在本地运行良好(来自Eclipse和独立的Tomcat),但每次从我的AWS EC2实例运行时都会失败javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
。
代码是:
// apiUrl looks like https://hsreplay.net/api/v1/games/jdUbSjsEcBL5rCT7dgMXRn
private String restGetCall(String apiUrl) throws Exception {
System.setProperty("javax.net.debug", "ALL");
SSLContextBuilder builder = new SSLContextBuilder();
builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build(),
SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER) {
@Override
protected void prepareSocket(SSLSocket socket) throws IOException {
try {
log.debug("************ setting socket HOST property *************");
PropertyUtils.setProperty(socket, "host", "hsreplay.net");
socket.setEnabledProtocols(new String[] { "SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2" });
}
catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException ex) {
log.error(ex.getMessage());
slackNotifier.notifyError(ex);
}
super.prepareSocket(socket);
}
};
CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
HttpGet httpGet = new HttpGet(apiUrl);
CloseableHttpResponse response1 = httpClient.execute(httpGet);
StringBuilder result = new StringBuilder();
try {
System.out.println(response1.getStatusLine());
HttpEntity entity1 = response1.getEntity();
BufferedReader rd = new BufferedReader(new InputStreamReader(entity1.getContent()));
String line;
while ((line = rd.readLine()) != null) {
result.append(line);
}
// do something useful with the response body
// and ensure it is fully consumed
EntityUtils.consume(entity1);
}
finally {
response1.close();
}
}
我也尝试了基本版本(没有任何覆盖SSLFactory方法),但无济于事。
另外,我没有设法从Tomcat上的javax.net.debug
获取日志(既不在远程也不在本地),所以如果您有任何想法,这也可能非常有用。
如果我能提供更多信息,请告诉我,非常感谢您的帮助!
塞巴斯蒂安
答案 0 :(得分:2)
握手失败可能是由许多不同原因引起的,例如错误的Java版本,服务器设置,设置主机名验证程序(无论如何都是坏主意),SNI ......这个问题中的当前信息不足以确定问题是什么。
查看服务器的SSLLabs report时,两个信息看起来很有趣:
如果您设置了主机名验证程序,那么第一个可能是旧Java版本的问题,甚至是JDK8的问题(虽然这对于此站点不是必需的,但您可以这样做。)
第二个可能是较旧的Java版本的问题,或者未安装无限强度的加密扩展。
答案 1 :(得分:0)
@ SteffenUlrich的回答让我走上了正确的轨道。问题确实是因为在开放的jdk 7中不支持ECDHE密码。我迁移到Oracle的JDK 8,现在情况正常。