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

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

  • 相关阅读:
    PHP远程下载图片,微信头像存到本地,本地图片转base64
    jQuery Validate自定义错误信息,自定义方法
    创建自己的composer包
    js,JQ获取短信验证码倒计时
    JQ JS复制到剪贴板
    js,JQuery 生成二维码
    js,JQuery实现,带筛选,搜索的select
    HTML5拖放牛刀小试
    HTML5上传图片预览功能
    一次dropzone体验
  • 原文地址:https://www.cnblogs.com/asd14828/p/2973278.html
Copyright © 2011-2022 走看看