c#请求https的接口一般都需要增加回调函数以忽略错误信息,我们拿HttpClient方法作为事例,回调函数如下所示
var handler = new HttpClientHandler()
{
ServerCertificateCustomValidationCallback = (message, cert, chain, error) => true,
};
HttpClient client = new HttpClient(handler);
在正常情况下,请求https以上代码都能请求正常,但今天在一台安装了windows7的电脑上去请求第三方的https接口发现返回了HandShake的错误信息。代码在另外一台电脑(windows10)上是能够正常请求的,于是开始了HandShake的排查。
HandShake 意为握手失败,我们都知道http是需要经过三次握手的,一开始我以为是否需要指定TLS版本,于是在上面代码的基础上增加了指定TLS版本,代码如下
var handler = new HttpClientHandler()
{
ServerCertificateCustomValidationCallback = (message, cert, chain, error) => true,
ClientCertificateOptions = ClientCertificateOption.Manual,
SslProtocols=System.Security.Authentication.SslProtocols.Tls12,
};
HttpClient client = new HttpClient(handler);
于是重新开始测试,发现返回依然是HandShake的错误,而且错误内容是一模一样。
最后只能通过抓包的方式检查在HandShake过程中哪一个环节出错了,抓包工具使用Wireshark。
首先验证了发送请求Client Hello上 TLS使用的是TLS12,服务端接口响应的Server Hello也是TLS12的,所以在这块上是一致的。
然后验证加密套件(Cipher Suite)后发现服务端接口使用的加密套件是
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
但在客户端请求的加密套件中并不存在,于是检查了windows7环境下支持的加密套件,发现确实没有,检查windows10环境下支持的加密套件是存在该加密套件的,于是到此为止基本确定是由于缺少服务端接口的加密套件导致的握手失败。
那么问题来了,如何解决呢?
网上查找了一圈并测试后根本就没有有用的解决方案,因为操作系统自身就不支持这种加密套件,最后只能换操作系统,升级到windows10,问题解决。
下图是升级到windows10后,请求https的抓包内容
上图这是一次完整的握手过程
从上图我们可以看到服务端接口使用的加密套件
从上图我们看到客户端请求时已经支持了该加密套件。