注意:相同的url在浏览器中是成功的,但它不是通过程序运行相同的url。Java代码:
String urlString= "https://<host>:<port>/TestProject";
URL url = new URL(urlString);
HttpsURLConnection con = (HttpsURLConnection)url.openConnection();
InputStream ins = con.getInputStream();
InputStreamReader isr = new InputStreamReader(ins);
BufferedReader in = new BufferedReader(isr);
String inputLine;
while ((inputLine = in.readLine()) != null) System.out.println(inputLine);
in.close();异常:
Exception in thread "main" javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:136)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1720)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:954)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1138)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1165)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1149)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:434)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:166)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1172)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:234)请尽早给出解决办法。如果知道的话,请给出得到这个场景的可能性,这对我非常有用。
终于找到了解决方案:
请查一下http://myjavacafe.blogspot.in/2015/01/exception-received-fatal-alert.html
发布于 2015-01-06 17:03:57
First:服务器可能记录有关问题的更多详细信息,这可能允许确定和解决实际问题。但是,既然你想要一个早期和“可能的”答案,而不是一个准确的答案,我看到的原因是:
版本太老了:服务器需要比您的Java提供的更新的协议。您似乎正在运行Java6,它只实现了TLSv1.0。如果服务器要求更高,它将失败握手,虽然要求高于1.0是有点争议,目前(它可能会成为接受和普遍在未来几年)。解决方案:使用Java8 (在其默认配置中),或者至少使用Java7,并覆盖它的默认配置,后者仅为客户端提供最多TLSv1.0。
版本太新了: TLS规范(all)要求服务器协商更新版本或其他能力更强的客户端到服务器功能,但有些服务器显然存在错误,反而导致握手失败。(浏览器/客户端通常通过回到旧协议来处理这一问题,这导致了最近的“贵宾狗”攻击。例如,见https://security.stackexchange.com/questions/71427/is-java-client-vulnerable-by-poodle和https://security.stackexchange.com/questions/70719/ssl3-poodle-vulnerability。)然而,Java6客户端不太可能触发这样的问题,如果最近的浏览器,特别是最近的几个浏览器能够连接,这是非常不可能的。但是如果这是解决方案的问题:使用旧的Java (很差),或者配置为使用旧的协议版本和可能很少的密码。
扩展:--类似地,有可能出现错误的服务器无法跳过未实现的扩展,正如规范所称的那样。同样,如果现代浏览器能够连接,这是非常不可能的。但是如果是这样的话,您就无法控制使用的扩展,所以解决方案: none。( Java中至少没有。您可以使用外部适配器,如stunnel,或应用程序级代理或中继。)
无共享密码:服务器不支持客户端提供的任何密码套件。--这不太可能是,除非您的JRE/JVM配置不当。Java实现了几乎所有定义的加密套件,默认情况下启用所有不太不安全的加密程序,除非Java6只在安装ECC密码提供程序时启用椭圆曲线密码套件,而它在默认情况下不是。服务器管理员可能合理地想要并且更喜欢EC,但是今天要求它是不谨慎的。如果ECC是问题解决方案:使用Java7或8,或者向Java6添加EC提供程序。--如果您的JRE/JVM配置得很糟糕--使用了服务器不应该同意解决方案的不安全密件:不这么做。
SNI:如果服务器需要服务器名称指示(这是当前虚拟主机通常需要的扩展),则服务器可能会失败,但您的客户端没有为其提供正确的值。但是,Java6 URLConnection(https)会自动从URL派生SNI,这与浏览器的方式相同,因此,如果同一个URL在最近的浏览器中工作,这不是问题所在。
Client auth:服务器可能需要使用证书进行客户端身份验证,通常缩写为要求(a)客户端证书,如果客户端不提供证书,或者可能没有提供正确的证书,则失败。您的浏览器可能被配置为自动提供正确的证书和密钥,但如果您使用多个不共享密钥存储库(例如Windows上的IE和Chrome )的浏览器,则可能不太可能出现这种情况。解决方案:将您的JVM/JRE配置为使用包含正确privateKeyEntry (密钥和证书或链)的密钥存储库,或者如果密钥存储库已经配置好,则将正确的privateKeyEntry放在该密钥存储库中。
https://stackoverflow.com/questions/27799559
复制相似问题