【问题标题】:How can you add a Certificate to WebClient (C#)?如何向 WebClient (C#) 添加证书?
【发布时间】:2011-01-05 04:58:22
【问题描述】:

我知道将证书添加到 HttpWebRequest 非常简单。但是,我还没有找到使用 WebClient 进行等效操作的方法。基本上,我想使用 WebClient 发送带有特定证书的 POST。

你将如何使用 WebClient 完成这个确切的代码:

var request = (HttpWebRequest) WebRequest.Create("my-url");
request.Method = "POST";
request.ClientCertificates.Add(new X509Certificate()); //add cert

【问题讨论】:

标签: c# httpwebrequest certificate webclient http-post


【解决方案1】:

只需继承WebClient,添加您自己的ClientCertificates 属性并覆盖WebClient.GetWebRequest(System.Uri) 方法。我没有时间将它从 VB 转换为 C#,但它应该是不言自明的:

Imports System.Net

Public Class WebClient2
    Inherits System.Net.WebClient

    Private _ClientCertificates As New System.Security.Cryptography.X509Certificates.X509CertificateCollection
    Public ReadOnly Property ClientCertificates() As System.Security.Cryptography.X509Certificates.X509CertificateCollection
        Get
            Return Me._ClientCertificates
        End Get
    End Property
    Protected Overrides Function GetWebRequest(ByVal address As System.Uri) As System.Net.WebRequest
        Dim R = MyBase.GetWebRequest(address)
        If TypeOf R Is HttpWebRequest Then
            Dim WR = DirectCast(R, HttpWebRequest)
            If Me._ClientCertificates IsNot Nothing AndAlso Me._ClientCertificates.Count > 0 Then
                WR.ClientCertificates.AddRange(Me._ClientCertificates)
            End If
        End If
        Return R
    End Function
End Class

【讨论】:

    【解决方案2】:

    您必须继承并覆盖一个或多个函数。

    class MyWebClient : WebClient
    {
        protected override WebRequest GetWebRequest(Uri address)
        {
            HttpWebRequest request = (HttpWebRequest)base.GetWebRequest(address);
            request.ClientCertificates.Add(new X509Certificate());
            return request;
        }
    }
    

    【讨论】:

    • 太棒了!一直试图弄清楚如何做到这一点太久了
    【解决方案3】:

    在我们的前端安装新证书时发生了一件有趣的事情。我们开始收到错误:

    “底层连接已关闭:无法为 SSL/TLS 安全通道建立信任关系。;底层连接已关闭:无法为 SSL/TLS 安全通道建立信任关系。;”

    我们通过转到每个前端并打开浏览器来处理错误。似乎 IE 正在缓存旧证书。通过打开浏览器,新证书生效。问题解决了!

    【讨论】:

      【解决方案4】:
      public class CertificateWebClient : WebClient
      {
          private readonly X509Certificate2 certificate;
      
          public CertificateWebClient(X509Certificate2 cert)
          {
              certificate = cert;
          }
      
          protected override WebRequest GetWebRequest(Uri address)
          {
              HttpWebRequest request = (HttpWebRequest)base.GetWebRequest(address);
      
              System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate(Object obj, X509Certificate X509certificate, X509Chain chain, System.Net.Security.SslPolicyErrors errors)
              {
                  return true;
              };
      
              request.ClientCertificates.Add(certificate);
              return request;
          }
      }
      

      现在您可以使用自签名证书了! ("底层连接已关闭:无法为 SSL/TLS 安全通道建立信任关系。;底层连接已关闭:无法为 SSL/TLS 安全通道建立信任关系。;")

              X509Certificate2 Cert = new X509Certificate2("client.p12", "1234", X509KeyStorageFlags.MachineKeySet);
      
              // Create a new WebClient instance.
              CertificateWebClient myWebClient = new CertificateWebClient(Cert);
      
              string fileName = Installation.destXML;
              string uriString = "https://xxxxxxx.xx:918";
              // Upload the file to the URI.
              // The 'UploadFile(uriString,fileName)' method implicitly uses HTTP POST method.
              byte[] responseArray = myWebClient.UploadFile(uriString, fileName);
      
              // Decode and display the response.
              Console.WriteLine("\nResponse Received.The contents of the file uploaded are:\n{0}",
                  System.Text.Encoding.ASCII.GetString(responseArray));
      

      【讨论】:

      • 如果您将证书添加到 webRequest.ClientCertificates 那么您不再需要覆盖 ServerCertificateValidationCallback ,这是一个全局设置,因此您会影响一切
      • 如果你有这个异常消息The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel添加这个ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 | SecurityProtocolType.Ssl3;
      猜你喜欢
      • 2011-08-03
      • 2014-06-30
      • 1970-01-01
      • 1970-01-01
      • 2010-11-21
      • 1970-01-01
      • 2017-02-16
      • 2016-10-25
      • 1970-01-01
      相关资源
      最近更新 更多