zoukankan      html  css  js  c++  java
  • 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;
                }
            }

    问题终于解决了,在这记录一下备忘。

  • 相关阅读:
    P1121 环状最大两段子段和
    无题
    cdoj 1485 柱爷搞子串 sam treap
    自然数幂和
    Gym 100341C AVL Trees NTT
    线性筛分解质因子
    codeforces 366 Ant Man dp
    UVALive 6914 Maze Mayhem 轮廓线dp
    hdu 5790 Prefix 字典树 主席树
    莫比乌斯反演个人小结
  • 原文地址:https://www.cnblogs.com/asd14828/p/2973278.html
Copyright © 2011-2022 走看看