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; } }
問題終於解決了,在這記錄一下備忘。
