C# 調用 Https協議web的服務 ssl證書(客戶端需要證書)


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;
            }
        }

問題終於解決了,在這記錄一下備忘。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM