先帖上关键代码:
var url1 = "https://uatdatarewardsgateway.92jiangbei.com/";
var json = "{\"date\":\"2020-05-21\"}";
string msg1 = string.Empty;
string msg2 = string.Empty;
var result = HttpPost(url1,json,out msg1);
var url2 = "https://test-order-open.i-vpoints.com/";
var result2 = HttpPost(url2, json, out msg2);
public static string HttpPost(string url,string json,out string msg)
{
msg = string.Empty;
var result = string.Empty;
var data = System.Text.Encoding.UTF8.GetBytes(json);
ServicePointManager.DefaultConnectionLimit = 1024;
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3
| SecurityProtocolType.Tls
| SecurityProtocolType.Tls11
| SecurityProtocolType.Tls12;
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
request.Method = "POST";
request.ContentType = "application/json";
try
{
using (var rs = request.GetRequestStream())
{
rs.Write(data, 0, data.Length);
}
using (HttpWebResponse wr = request.GetResponse() as HttpWebResponse)
{
using (var wrs = wr.GetResponseStream())
{
using (var sr = new StreamReader(wrs))
{
result = sr.ReadToEnd();
msg = "OK";
}
}
}
}
catch (Exception ex)
{
msg = ex.Message;
}
return result;
}
===================================================================
以上代码经测试:
1.win7和win2008下面url1无法连接,url2正常;
2.win10下面两个都正常。
3.url1地址在win7下的chrome、firefox、postman等都可以正常访问。
请问怎么处理以上代码在win7和win2008下无法与url1建立https连接?
你可以把错误消息贴一下,或者用wireshark在win7上抓包看一看tls的哪个环节出错了。
url1使用也是tls12,现在连接无法建立,会不会抓不到包?
@yswenli: 不会的,无法建立连接也可抓包的,可以看出来什么原因导致的无法建立连接的。
@yswenli: 我刚看了一下你这两个域名,证书都是同一个根证书签发的,所以可以排除2。
1的原因可能性比较大。
@blackheart: 我用chrome和firefox,postman之类在win7下面都可以与url1建立连接,就是上述C#代码不行,不过我先抓包试试看~
@yswenli: 那就说明很可能是c#中的代码没有和服务端协商好tls。。。
emmm,上面的,浏览器访问不到,下面的可以。。。
另外,报错信息是什么?
上面那个你报404了?第一个地址在Win7下无法建立连接~
@yswenli: 对,Whitelabel Error Page
不过也是,你代码是post请求,如果get什么都不返回,这也正常
@顾晓北: 我现在的问题是在C#代码中的出现的问题,浏览器和postman之类的不管在win7和还是win10两个地址都能正常使用
url1正常呼叫可以接收到什麼結果?
我的问题不是收到什么内容,是以上代码的url1在win7无法建立Https连接~
@yswenli:
你都知道問題出在無法建立https連接了,還想問什麼..
你使用的是什么编译器什么环境?Visual Studio ?NetCore?还是什么,应该是你的编译环境的问题,使用postman或者浏览器能访问,在编译器调试代码不能访问,那就是你的编译环境有问题
我这个是用.net framework 4.5,编译完的的Exe在win10下面可以正常访问url1,在win7下面不行~
@yswenli: 你要自查一下,比如在win10系统下使用VS 2017 开发代码,能完美编译并使用,但是你突然把在win10环境vs2017编译的exe程序放在win7上面运行,他就会缺少引用程序、net framework版本不兼容等问题。
暂定解决办法有以下:
1.换低版本的编译器(如VS2017换到VS2013)来编译项目
2.在win7环境重新安装一个.net 4.5环境
问题定位到了,是因为url1这个地址的服务器采用的http2.0,而windows7下面的.net framework不支持
改为httpclient就能发现这个异常提示
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
var url1 = "https://uatdatarewardsgateway.92jiangbei.com/";
var json = "{\"date\":\"2020-05-21\"}";
try
{
var httpclientHandler = new HttpClientHandler()
{
ServerCertificateCustomValidationCallback = (message, cert, chain, error) => true,
AllowAutoRedirect = true,
ClientCertificateOptions = ClientCertificateOption.Automatic,
SslProtocols = System.Security.Authentication.SslProtocols.Tls12
};
HttpClient httpClient = new HttpClient(httpclientHandler);
var body = new StringContent(json);
var request = new HttpRequestMessage(HttpMethod.Post, url1) { Version = new Version(2, 0), Content = body };
HttpResponseMessage response = httpClient.SendAsync(request).Result;
response.EnsureSuccessStatusCode();
string responseBody = response.Content.ReadAsStringAsync().Result;
Console.WriteLine(responseBody);
}
catch (Exception ex)
{
Console.WriteLine("Message :{0} ", ex.Message);
}
你的url1的服务端是只支持HTTP/2吗?我记得1.1和2是可以同时支持的,客户端如果不支持2,可以继续用1.1。
不过HTTP/2的性能要好于1.1,客户端可控的话只支持2也挺好的,省去了ALPN的开销。
@blackheart: 这是别人的服务器,我这里只是访问,结果他们老的接口没有问题,五一后的新接口全都访问不了,我的服务器是WinServer2008,换到的winServer2016服务器就能正常访问他们的接口了~
@yswenli: 哦哦,那就直接用HTTP/2得了。 HttpClient不要每次都new一个,全局维持一个就可以,它内部会自动维护一个连接池的。
@blackheart: 是的,搞的我们只能用winServer2016了~
@yswenli:
curl --http1.1 https://uatdatarewardsgateway.92jiangbei.com/
curl --http2 https://uatdatarewardsgateway.92jiangbei.com/
两个都能访问,说明服务器是同时支持1.1和2的。
也许还是在1.1的时候协商tls的过程中的问题(而你这边升级到了winServer2016,支持的tls版本明显是升高了)。
如果想查出来根本原因,在报错的win7上wireshark抓包应该是最有效的办法。
@blackheart: 不是这个意思,都知道http2支持http1.1,但是http2在头部有特殊的字段,例如:method:post这种,这个估计在类似win7这样的老系统的被认为是不合法地
@yswenli:
你说的这个是客户端和服务端协商升级2后才采用的2的专属的头部压缩的表现形式。
我的意思是服务端同时支持2和1.1,客户端只支持1.1,那么这个时候是完全可以通信的,并且会采用1.1来通信。客户端就根本不知道2的存在。
@yswenli:
另外,不是2支持1.1,它俩底层是完全不一样的(上层语义相同)。
服务端可以选择只支持1.1,也可以选择只支持2,也可以选择同时支持1.1和2。
@blackheart: 现在情况就是我这里不支持2.0,只支持1.1。经测试如果2.0头部将是正常的,如果http2在支持1.1的时候,头部会包含
:authority: uatdatarewardsgateway.92jiangbei.com
:method: GET
:path: /
:scheme: https
客户端是完全知道这个是不是2的服务器
@yswenli: 和头部完全没关系的,你这个代码是已经是2的情况下的。
你了解下ALPN吧。
@blackheart: 是的,怎么改代码都是没用的,对于.net来说这个alpn是系统层的,只能换系统了
@yswenli: 我说的不是这个意思。我说是你可以在win7上用wireshark抓一下报错的时候的包,它会告诉你真正的原因是什么。因为url1明显是独立支持1.1和2的,那就可以排除不是win7不支持2的问题,至于真正的原因到底是什么(不管它是不是通过alpn升级到了h2,还是根本就没有alpn这个过程)抓的包是都会告诉你的。
有道理,后续有时间再深研下,先确认了win7不行换系统发布了~
@yswenli:
我在win7上给你抓出来了。
win7上的tls的client hello中的加密套件。
url1的server返回的消息。
tls handshake failed (40)
。
@yswenli:
url1支持的tls cipher suites
太少了(只有3个:https://myssl.com/uatdatarewardsgateway.92jiangbei.com?domain=uatdatarewardsgateway.92jiangbei.com&status=q),win7中默认的cipher suites
均不在这三个之中,然后导致的tls握手失败。
而url2支持的tls cipher suites
则很全面(https://myssl.com/test-order-open.i-vpoints.com?domain=test-order-open.i-vpoints.com&status=success)。
故而导致的结果就是win7上url1默认不能正常访问,而url2可以。
@blackheart: 666
楼主,请问解决方案是什么?win7下无解么?
建议改进一下排版,支持 markdown 语法
– dudu 4年前