Thread-6,RECV TLSv1 ALERT:致命,handshake_failure

这段代码出了什么问题,它应该信任所有主机,但它不会…

它适用于例如google.com,但没有在我的机器上本地运行的API网关服务,为什么?

SSL调试输出

触发种植SecureRandom播种SecureRandom忽略不支持的密码套件:TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 …忽略不支持的密码套件:TLS_RSA_WITH_AES_128_CBC_SHA256允许不安全的重新协商:false允许传统的hello消息:true是初始握手:true是否是安全重新协商:false Thread-6,setSoTimeout(0 )调用%%没有缓存的客户端会话*** ClientHello,TLSv1 RandomCookie:GMT:1434280256 bytes = {216 … 40}会话ID:{}密码套件:[TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,…… SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA,SSL_RSA_WITH_RC4_128_MD5,TLS_EMPTY_RENEGOTIATION_INFO_SCSV]压缩方法:{0}扩展椭圆曲线,曲线名称:{secp256r1 .. secp256k1}扩展ec_point_formats,格式:[未压缩]

Thread-6,WRITE:TLSv1 Handshake,length = 163 Thread-6,READ:TLSv1 Alert,length = 2 Thread-6,RECV TLSv1 ALERT:fatal,handshake_failure Thread-6,名为closeSocket()Thread-6,处理exception: javax.net.ssl.SSLHandshakeException:**

收到致命警报:handshake_failure


**

import java.io.InputStreamReader; import java.io.Reader; import java.net.URL; import java.net.URLConnection; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import java.security.cert.X509Certificate; public class ConnectHttps { public static void main(String[] args) throws Exception { /* * fix for * Exception in thread "main" javax.net.ssl.SSLHandshakeException: * sun.security.validator.ValidatorException: * PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: * unable to find valid certification path to requested target */ TrustManager[] trustAllCerts = [ [ getAcceptedIssuers: { -> null }, checkClientTrusted: { X509Certificate[] certs, String authType -> }, checkServerTrusted: { X509Certificate[] certs, String authType -> } ] as X509TrustManager ] SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCerts, new java.security.SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); // Create all-trusting host name verifier HostnameVerifier allHostsValid = new HostnameVerifier() { public boolean verify(String hostname, SSLSession session) { return true; } }; // Install the all-trusting host verifier HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid); /* * end of the fix */ //URL url = new URL("https://google.com"); //WORKS URL url = new URL("https://localhost:8090"); // DOES NOT WORK, WHY? URLConnection con = url.openConnection(); Reader reader = new InputStreamReader(con.getInputStream()); while (true) { int ch = reader.read(); if (ch==-1) { break; } System.out.print((char)ch); } } } 

运行此处的代码表明客户端未启用TLSv1.2:

支持的协议:5
SSLv2Hello
在SSLv3
使用TLSv1
TLSv1.1
TLSv1.2工作

启用协议:2
在SSLv3
使用TLSv1

..它应该信任所有主机,但它不会..

.. RECV TLSv1警告:致命,handshake_failure线程-6

来自服务器的握手失败警报与客户端上的服务器证书的validation无关,因此无法通过禁用证书validation来停止。 很多事情都可能导致这样的失败,例如没有通用密码,不支持的协议版本,缺少SNI扩展(仅支持从JDK7开始)。 由于服务器发出错误,您可能会在服务器日志消息中找到有关该问题的更多详细信息。

编辑:从服务器日志中可以看到问题的原因:

error handling连接:SSL协议错误错误:1408A0C1:SSL例程:SSL3_GET_CLIENT_HELLO:无共享密码

这意味着客户端和服务器之间没有通用密码。

造成这种情况的典型原因是服务器上的证书设置错误。 如果您未配置任何证书,则服务器可能需要使用ADH密码进行匿名身份validation,这些密码通常在客户端未启用。 我建议您检查是否可以连接浏览器。

另一个常见的错误配置是禁用服务器上的所有SSLv3密码,相信这是禁用SSL3.0协议所必需的(事实并非如此)。 这有效地禁用了除TLS 1.2引入的一些新密码之外的所有密码。 现代浏览器仍然可以连接,但不是老客户端。 在这种情况下可以看到这种错误配置(来自评论):

从服务器日志,接口密码:FIPS:!SSLv3:!aNULL ,,

!SSLv3禁用可用于SSL3.0 及更高版本的所有密码。 这实际上只留下了TLS1.2密码,因为没有新的密码与TLS1.0和TLS1.1。 由于客户端似乎只支持TLS1.0,因此不会有共享密码:

…写:TLSv1握手

在密码中使用!SSLv3通常是由于缺乏对协议版本和密码之间差异的理解。 要禁用SSLv3,您应该只相应地设置协议,而不是密码。