public class restop { private string url = ""; public string Url { get { return url; } set { url = value; } } private string clientp12path = ""; public string Clientp12path { get { return clientp12path; } set { clientp12path = value; } } private string clientp12PassWord = ""; public string Clientp12PassWord { get { return clientp12PassWord; } set { clientp12PassWord = value; } } public restop() { } public string send(string s) { string retrunstr = ""; //类似浏览器确认证书合法方法的绑定 //如果觉得写一个委托方法麻烦,可以直接使用匿名委托 ServicePointManager.ServerCertificateValidationCallback = RemoteCertificateValidate; ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3; Uri uri = new Uri(@url); HttpWebRequest request = HttpWebRequest.Create(uri) as HttpWebRequest; byte[] bs = Encoding.UTF8.GetBytes(s);
//这2句代码表示如果要求客户端证书,将客户端证书加入request,不需要客户端证书的https请求则不需要此代码
//需导入xx.p12证书文件 clientp12path为文件所在路径clientp12password为证书密码
InstallCertificate(clientp12path, clientp12PassWord, StoreLocation.CurrentUser, StoreName.My);
X509Certificate cer = new X509Certificate(clientp12path, clientp12PassWord); request.ClientCertificates.Add(cer); request.ContentType = "text/plain"; request.Method = "post"; request.KeepAlive = false; request.ProtocolVersion = HttpVersion.Version10; request.Proxy = null; //request.UserAgent = DefaultUserAgent; using (Stream reqStram = request.GetRequestStream()) { reqStram.Write(bs, 0, bs.Length); reqStram.Close(); } HttpWebResponse response = request.GetResponse() as HttpWebResponse; using (StreamReader reader = new StreamReader(response.GetResponseStream())) { retrunstr = reader.ReadToEnd(); } return retrunstr; } private static bool RemoteCertificateValidate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors error) { // trust any certificate!!! //System.Console.WriteLine("Warning, trust any certificate"); //为了通过证书验证,总是返回true return true; } //导入证书 public static bool InstallCertificate(string certFilePath, string password, StoreLocation location, StoreName storeName) { try { if (!File.Exists(certFilePath)) { return false; } byte[] certData = File.ReadAllBytes(certFilePath); X509Certificate2 cert = new X509Certificate2(certData, password, X509KeyStorageFlags.Exportable); X509Store store = new X509Store(storeName, location); store.Open(OpenFlags.MaxAllowed); store.Remove(cert); store.Add(cert); store.Close(); return true; } catch (Exception ex) { return false; } } }
总结:
由于是首次接触C#调用Https这方面的技术,在网上找了好多资料都说是用以下代码
ServicePointManager.ServerCertificateValidationCallback = RemoteCertificateValidate; X509Certificate cer = new X509Certificate(“xx.p12”, "xx"); request.ClientCertificates.Add(cer);
我总是报以下错误
未处理 System.Net.WebException Message=基础连接已经关闭: 发送时发生错误。 Source=System StackTrace: 在 System.Net.HttpWebRequest.GetResponse() 在 ConsoleAppRest.restop.send(String s) 位置 E:\大气背景站\https\ConsoleAppRest\ConsoleAppRest\restop.cs:行号 65 在 ConsoleAppRest.Program.Main(String[] args) 位置 E:\大气背景站\https\ConsoleAppRest\ConsoleAppRest\Program.cs:行号 16 在 System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) 在 System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) 在 Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() 在 System.Threading.ThreadHelper.ThreadStart_Context(Object state) 在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx) 在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 在 System.Threading.ThreadHelper.ThreadStart() InnerException: System.IO.IOException Message=由于远程方已关闭传输流,身份验证失败。 Source=System StackTrace: 在 System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest) 在 System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest) 在 System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest) 在 System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest) 在 System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest) 在 System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest) 在 System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest) 在 System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest) 在 System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest) 在 System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest) 在 System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult) 在 System.Net.TlsStream.CallProcessAuthentication(Object state) 在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx) 在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 在 System.Net.TlsStream.ProcessAuthentication(LazyAsyncResult result) 在 System.Net.TlsStream.Write(Byte[] buffer, Int32 offset, Int32 size) 在 System.Net.PooledStream.Write(Byte[] buffer, Int32 offset, Int32 size) 在 System.Net.ConnectStream.WriteHeaders(Boolean async) InnerException:
找了好久终于找到还是加载证书问题,有人说是的手动导入证书照下面方法导入证书之后程序是能运行了,但太麻烦了你不能让用户去操作这些哇。
操作如下: 1. 单击 开始 ,单击 运行 ,键入 mmc ,然后单击 确定 。 2. 在 文件 菜单上单击 添加/删除管理单元 。 3. 在 添加/删除管理单元 对话框中,单击 添加 。 4. 在 添加独立管理单元 对话框单击 证书 ,然后单击 添加 。 5. 在在 证书管理单元中 对话框中单击 计算机帐户 ,然后单击 下一步 6. 在 选择计算机 对话框中,单击 完成 。 7. 在 添加独立管理单元 对话框单击 关闭 ,然后单击 确定 。 8. 展开 证书 (本地计算机) ,展开 个人 ,然后单击 证书 。 9. 右键 -》 所有任务-》导入 选择你的证书导入 要注意的是: 一定要导入证书+私钥,只导入证书是不行的 即,要导入pfx或者p12文件,而不是导入cer文件
之后在网上又找到程序导入证书的方法
public static bool InstallCertificate(string certFilePath, string password, StoreLocation location, StoreName storeName) { try { if (!File.Exists(certFilePath)) { return false; } byte[] certData = File.ReadAllBytes(certFilePath); X509Certificate2 cert = new X509Certificate2(certData, password, X509KeyStorageFlags.Exportable); X509Store store = new X509Store(storeName, location); store.Open(OpenFlags.MaxAllowed); store.Remove(cert); store.Add(cert); store.Close(); return true; } catch (Exception ex) { return false; } }
问题终于解决了,在这记录一下备忘。