访问https接口报错 基础连接已经关闭: 未能为 SSL/TLS 安全通道建立信任关系
详细错误信息如下
请求错误信息:发生一个或多个错误。System.Net.Http.HttpRequestException: An error occurred while sending the request. --->
System.Net.WebException: 基础连接已经关闭: 未能为 SSL/TLS 安全通道建立信任关系。 ---> System.Security.Authentication.AuthenticationException: 根据验证过程,远程证书无效。
在 System.Net.TlsStream.EndWrite(IAsyncResult asyncResult)
在 System.Net.ConnectStream.WriteHeadersCallback(IAsyncResult ar)
--- 内部异常堆栈跟踪的结尾 ---
在 System.Net.HttpWebRequest.EndGetRequestStream(IAsyncResult asyncResult, TransportContext& context)
在 System.Net.Http.HttpClientHandler.GetRequestStreamCallback(IAsyncResult ar)
--- 内部异常堆栈跟踪的结尾 ---
原本这个接口是http协议的,后来第三方为了安全使用了https协议😳
致使我的方法不支持https访问而报错🤔
我原本的调用方法如下
public static string Post(string httpUrl, string requestJson, ref List<string[]> msg, string source) { string strRet = string.Empty; int doop = 1; HttpResponseMessage response = new HttpResponseMessage(); do { if (doop != 1) Thread.Sleep(60000); try { using (var client = new HttpClient()) { HttpContent httpContent = new StringContent(requestJson); httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json"); response = client.PostAsync(httpUrl, httpContent).Result; if (response.IsSuccessStatusCode) { strRet = response.Content.ReadAsStringAsync().Result; msg.Add(new string[] { "Success", "post 发送的第" + doop + "次请求数据[" + httpUrl + "],[" + requestJson + "]" }); } else { msg.Add(new string[] { "Error","post 的第" + doop + "次请求失败,数据[" + httpUrl + "],[" + requestJson + "]" + "\n" + "请求错误信息:" + response.ReasonPhrase }); } } } catch (Exception ex) { strRet = string.Empty; msg.Add(new string[] { "Error","post 发送的第" + doop + "次请求数据[" + httpUrl + "],[" + requestJson + "]" + "\n" + "请求错误信息:" + ex.Message + ex.InnerException }); } doop++; } while (doop <= 10 && !response.IsSuccessStatusCode); return strRet; }
在网上查阅了资料找到了解决方案,大致如下
调用http访问前写这句话 ServicePointManager.CertificatePolicy = new AcceptAllCertificatePolicy(); internal class AcceptAllCertificatePolicy : ICertificatePolicy { public AcceptAllCertificatePolicy() { } public bool CheckValidationResult(ServicePoint sPoint, X509Certificate cert, WebRequest wRequest, int certProb) { // Always accept return true; } }
这么写有点麻烦,但是能解决问题
查看了ServerCertificateValidationCallback属性,发现它的类型为RemoteCertificateValidationCallback的委托,为何不直接写一个参数相同的方法直接返回true呢
public delegate bool RemoteCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors);
解决方案
ServicePointManager.ServerCertificateValidationCallback = Callback; private static bool Callback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; }
最终我的代码如下
public static string Post(string httpUrl, string requestJson, ref List<string[]> msg, string source) { string strRet = string.Empty; int doop = 1; HttpResponseMessage response = new HttpResponseMessage(); do { if (doop != 1) Thread.Sleep(60000); try { using (var client = new HttpClient()) { ServicePointManager.ServerCertificateValidationCallback = Callback; HttpContent httpContent = new StringContent(requestJson); httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json"); response = client.PostAsync(httpUrl, httpContent).Result; if (response.IsSuccessStatusCode) { strRet = response.Content.ReadAsStringAsync().Result; msg.Add(new string[] { "Success", "post 发送的第" + doop + "次请求数据[" + httpUrl + "],[" + requestJson + "]" }); } else { msg.Add(new string[] { "Error","post 的第" + doop + "次请求失败,数据[" + httpUrl + "],[" + requestJson + "]" + "\n" + "请求错误信息:" + response.ReasonPhrase }); } } } catch (Exception ex) { strRet = string.Empty; msg.Add(new string[] { "Error","post 发送的第" + doop + "次请求数据[" + httpUrl + "],[" + requestJson + "]" + "\n" + "请求错误信息:" + ex.Message + ex.InnerException }); } doop++; } while (doop <= 10 && !response.IsSuccessStatusCode); return strRet; } private static bool Callback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; }
By听雨的人