今天在项目遇到了Received fatal alert: handshake_failure 的问题,直译就是握手失败了,说实话,我也是第一次碰到这种情况。在各大论坛,各种技术博客的海洋里,仍然没有解决我的问题。最后捡漏发现了这个原因,真的太出乎意料了。

首先和大家说一下网上的一些经验和处理办法,算是一个总结。

我们用curl 和 postman 发送请求,都可以握手成功,唯独用代码不能请求成功。handshake_failure的原因绝不是一种。

原因一: Https 的协议版本不一致。协议有 TLSv1.2,TLSv1.1,SSLv3

如何来确定这个问题?

1:如果你是在本机运行,可以这么做,写一个通讯客户端(只用来测试握手的)

代码是我临时引用别人的,我的在服务器上不好拿下来。

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.URL;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;  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;    public class HttpsTest {  private static class TrustAnyTrustManager implements X509TrustManager {  @Overridepublic void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {  }  @Overridepublic void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {  }  @Overridepublic X509Certificate[] getAcceptedIssuers() {  return null;  }  }  private static class TrustAnyHostnameVerifier implements HostnameVerifier {  public boolean verify(String hostname, SSLSession session) {  return true;  }  }  public static String sendHttps(String url) throws Exception {  InputStream in = null;  OutputStream out = null;  String returnValue = "";  try {  //SSLContext sc = SSLContext.getInstance("SSL");
//            System.setProperty("https.protocols", "TLSv1.2,TLSv1.1,SSLv3");
//            SSLContext sc = SSLContext.getInstance("TLS", "SunJSSE");SSLContext sc = SSLContext.getInstance("TLS");  sc.init(null, new TrustManager[] { new TrustAnyTrustManager() }, new java.security.SecureRandom());  URL console = new URL(url);  HttpsURLConnection conn = (HttpsURLConnection) console.openConnection();  conn.setSSLSocketFactory(sc.getSocketFactory());
//            conn.setHostnameVerifier(new TrustAnyHostnameVerifier());  conn.setRequestMethod("POST");conn.connect();  InputStream is = conn.getInputStream();  DataInputStream indata = new DataInputStream(is);  returnValue = indata.readLine();              conn.disconnect();  } catch (ConnectException e) {  e.printStackTrace();throw e;  } catch (IOException e) {  e.printStackTrace();throw e;  } finally {  try {  in.close();  } catch (Exception e) {  }  try {  out.close();  } catch (Exception e) { }  }  return returnValue;  }  public static void main(String[] args) throws Exception {  System.out.println(sendHttps("https://finance-23055.beta.qunar.com"));  }
}
## 代码转载 https://blog.csdn.net/dzy_001/article/details/81012959

然后在运行参数里面设置

-Djavax.net.debug=all 

然后运行,会出现下面的,内容很多,可以找到下面这些。

main, WRITE: TLSv1.2 Handshake, length = 191  ## 这是客户端发出的版本
[Raw write]: length = 196main, READ: TLSv1.2 Alert, length = 2 ## 这是服务端返回的版本
main, RECV TLSv1.2 ALERT:  fatal, handshake_failure

很遗憾,这不能解决我的问题,因为客户端服务端都是TLSv1.2。如果你们发现这两个版本不一样的话,你就属于这种情况了,如何解决,请看其他文章吧,我就不细说了,给两个推荐。

http://www.voidcn.com/article/p-xjnaqnwd-bqu.html

https://blog.csdn.net/u014644574/article/details/83381303

2:服务器不支持此协议

SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure
然后用openssl s_client -connect finance-23055.beta.qunar.com:443 -state -debug -tls1 -msg看到的message回复是这样:read from 0xb644fc0 [0xb689760] (5 bytes => 5 (0x5))
0000 - 15 03 01 00 02 …..
read from 0xb644fc0 [0xb689765] (2 bytes => 2 (0x2))
0000 - 02 28
其中0x15代表的是alert,而0x28代表的handshake failure

这样很难发现服务器的支持协议,很慢,还要猜,还可能猜不准

https://www.ssllabs.com/ssltest/

进入这个地址,输入你要测试的服务器地址。然后就会出一个报告,很详细。

协议很清楚 看出是否支持。下面还有更加详细的,自己试试 吧。

3:SSL算法不支持

curl -d "" -k https://IP:port/tests -v

使用上述命令,我们可以清晰看到执行过程。

其中有一行是这样的

SSL connection using  ********  ## * 代表了curl使用的算法

这个算法我们就是我们的了。那看我们的程序 是否支持这种算法呢?

ctx.getSupportedSSLParameters().getCipherSuites()
ctx.getSocketFactory().getDefaultCipherSuites()
ctx.getSocketFactory().getSupportedCipherSuites()## ctx 是SSLContext 对象

打印一下,看curl的算法,是否在我们java的支持范围内。

解决办法请参考:https://blog.csdn.net/qq_36783371/article/details/80665901

4:也就是我这种了,最悲哀的吧。看我的上述代码了么,去掉这一段,就不会握手失败了。这个验证也是在握手过程内。

private static class TrustAnyHostnameVerifier implements HostnameVerifier {  public boolean verify(String hostname, SSLSession session) {  return true;  }  } 

好了,这就是我总结的所有了。

HTTPS请求 Received fatal alert: handshake_failure异常---与众不同的原因相关推荐

  1. SoapUI 请求 https 报 javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

    SoapUI 请求 https 报 javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure 在 E:\ ...

  2. 使用Java访问https接口javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

    jdk1.6,证书:SHA256+TLSv1.2 使用Java访问https://**************** 接口     控制台提示握手失败错误:javax.net.ssl.SSLHandsh ...

  3. javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

    问题描述:在jdk1.7环境中使用HttpURLConnection发送https请求时,异常了 javax.net.ssl.SSLHandshakeException: Received fatal ...

  4. javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure问题解决

    最近在生产环境调用Https接口出现这个问题javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure,经 ...

  5. 解决javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure报错

    背景 java版本1.8.0,今天尝试用Java去访问一个https接口,但抛出下面的异常: javax.net.ssl.SSLHandshakeException: Received fatal a ...

  6. 搞定 javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure 问题!

    开始碰到这个问题找遍了各种方法,其实还是需要耐心的先搞清楚原因再想方法靠谱,这里也总结下这个异常的多种解决方案, 首先先理解下为什么出现handshake?字面理解是客户端与服务端握手失败,能导致握手 ...

  7. 访问https,抛出的异常javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

    话说这个坑有点深,查阅大半个百度几乎没解决 部分网友解释:是因为jdk中jce的安全机制导致报的错,按照大家的方式,要去oracle官网下载对应的jce包替换jdk中的jce包. jce所在地址: % ...

  8. 排查https请求出现received fatal alert: internal_error的问题

    目录 背景 https网络协议交互 net.debug查看信息 Apache Httpclient与 Netty的http请求 server_name 错误原因 修复方案 方案一 方案二 背景 通知某 ...

  9. Could not transfer artifact (https://repo.maven.apache.org/maven2): Received fatal alert: protocol_v

    异常信息 Failed to read artifact descriptor for org.slf4j:slf4j-api:jar:1.7.2 org.eclipse.aether.resolut ...

最新文章

  1. cf1139D. Steps to One(dp)
  2. Docker学习笔记【一】
  3. Building your training into your researcing
  4. shell+mysql获取数据库名_shell操作mysql数据库
  5. 【数据结构与算法】判断单链表是否有环的算法
  6. etc php5 conf.d,php – nginx:[emerg]“location”指令不允许在/etc/nginx/conf.d/default.conf中使用:...
  7. android 线程池 怎么用,android中的线程池 怎么用
  8. gitolite安装及配置
  9. 医院后勤管理软件系统助力医院后勤管理实施国家数字低碳战略
  10. 自动量程万用表的实现原理_自动量程万用表模块设计方案[图]
  11. linux+mint+xfce开WiFi,为LinuxMint XFCE增加一键共享
  12. Mybatis拦截器 拦截所有更新操作
  13. 如何下载网页中的小视频
  14. 剪轴凝截Analdeta.Tessera.Pro.v3.2.2.Build.2015.10.05.Win64 1CD
  15. 苹果PD20W火爆方案看这里!!!
  16. oracle 对表重建索引,oracle 重建索引方法 分析
  17. 高效率完成一次接入80个手游渠道SDK——游戏接入SDK服务端篇
  18. 微服务之Spring Cloud Alibaba Nacos基础学习
  19. 微信开发工具无法支持vue文件
  20. c语言打出的王字图形图形,C语言编程宝典(王大刚) 3 关键字和标识符

热门文章

  1. 计算机系统时间无法修改,笔记本电脑系统时间无法修改该怎么处理
  2. Android常用学习网站
  3. maven项目集成findbugs详解
  4. 面向对象数据库(Object Oriented Databases)
  5. vba操作IE浏览器
  6. 《惢客创业日记》2021.08.10-11(周二)问了凉粉儿两个问题
  7. C++11 chrono 库
  8. 文件框上传文件选中文件后路径变成了C:\fakepath
  9. 第四章:搭建Windows server AD域和树域
  10. 家用计算机做服务器,将服务器CPU安装到家用PC上合适?_服务器_服务器产业-中关村在线...