最近的项目中用到了调用https的接口的功能,编写出程序后在我自己的电脑上运行没有问题,但是在同事的电脑上和服务上都没有办法正常运行,提示“请求被中止: 未能创建 SSL/TLS 安全通道”,最后在项目经理的帮助下和网上查找了大量的资料,以及做了大量的测试下终于解决了问题,所以想和大家分享下,避免大家像我一样耗费太多时间在这个问题上。
首先感谢广大网友的分享的解决方法和项目经理的帮助,否则我可能还是找不到问题的解决方法。
这是我写的代码:
using System;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
namespace ssl
{
class Program
{
static void Main(string[] args)
{
try
{
var keystorefile = @"D:\xxx\xxxx.p12";
var keypasswd = "xxxxxx";
var url = "https://xxxxxxxxxx";
var data = Encoding.UTF8.GetBytes("xxxx");
var request = (HttpWebRequest)WebRequest.Create(url);
//X509Certificate2 支持读取.p12格式的证书
var cer = new X509Certificate2(keystorefile, keypasswd);
request.ClientCertificates.Add(cer);
ServicePointManager.ServerCertificateValidationCallback += (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)=>
{
return true;
};
//ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = data.Length;
using (var stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
var response = (HttpWebResponse)request.GetResponse();
var context = new StreamReader(response.GetResponseStream(),Encoding.UTF8).ReadToEnd();
Console.WriteLine(context);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.Read();
}
}
}
在有的电脑会上运行会出现"请求被中止: 未能创建 SSL/TLS 安全通道"的问题,原因似乎是由于直接从磁盘读取证书导致的,但是具体原因不清楚,解决方法就是将证书导入系统,然后再调用系统证书存储空间中的证书。方法如下:
//查找我们导入的证书
X509Store certStore = new X509Store(StoreName.My, StoreLocation.LocalMachine);
certStore.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certCollection = certStore.Certificates.Find(X509FindType.FindBySubjectName, "安装的证书名字", false);
另一个原因是用户权限不够,可以使用winhttpcertcfg.exe工具,进入cmd 执行如下命令:
winhttpcertcfg -g -c LOCAL_MACHINE\MY -s "安装的证书名字" -a "Eeveryone"
最后的代码是这样:
using System;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
namespace ssl
{
class Program
{
static void Main(string[] args)
{
try
{
var url = "https://xxxxxxxxxx";
var data = Encoding.UTF8.GetBytes("xxxx");
var request = (HttpWebRequest)WebRequest.Create(url);
//X509Certificate2 支持读取.p12格式的证书
//查找我们导入的证书
X509Store certStore = new X509Store(StoreName.My, StoreLocation.LocalMachine);
certStore.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certCollection = certStore.Certificates.Find(X509FindType.FindBySubjectName, "安装的证书名字", false);
request.ClientCertificates.Add(certCollection[0]));
ServicePointManager.ServerCertificateValidationCallback += (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)=>
{
return true;
};
//ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = data.Length;
using (var stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
var response = (HttpWebResponse)request.GetResponse();
var context = new StreamReader(response.GetResponseStream(),Encoding.UTF8).ReadToEnd();
Console.WriteLine(context);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.Read();
}
}
}
参考资料:
https://www.cnblogs.com/jesselzj/p/6007118.html
https://www.cnblogs.com/ccsharp/p/3270344.html