¿Cómo se puede agregar un Certificado a WebClient (C #)?

Sé que es bastante simple agregar un certificado a HttpWebRequest. Sin embargo, no he encontrado una forma de hacer el equivalente usando WebClient. Básicamente, quiero enviar un POST con un certificado específico usando WebClient.

¿Cómo lograría este código exacto usando WebClient?

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

Debe subclasificar y anular una o más funciones.

 class MyWebClient : WebClient { protected override WebRequest GetWebRequest(Uri address) { HttpWebRequest request = (HttpWebRequest)base.GetWebRequest(address); request.ClientCertificates.Add(new X509Certificate()); return request; } } 
 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; } } 

¡Ahora puedes con cert auto firmado! (“La conexión subyacente se cerró: no se pudo establecer una relación de confianza para el canal seguro SSL / TLS. La conexión subyacente se cerró: no se pudo establecer una relación de confianza para el canal seguro 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)); 

Simplemente ClientCertificates WebClient , agregue su propia propiedad ClientCertificates y anule el método WebClient.GetWebRequest(System.Uri) . No tengo tiempo para convertir esto a C # de VB, pero debería ser bastante autoexplicativo:

 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 

Algo interesante sucedió cuando se instaló un nuevo certificado en nuestros front-ends. Empezamos a recibir el error:

“La conexión subyacente estaba cerrada: no se pudo establecer una relación de confianza para el canal seguro SSL / TLS. La conexión subyacente se cerró: no se pudo establecer una relación de confianza para el canal seguro SSL / TLS”.

Nos ocupamos del error yendo a cada interfaz y abriendo el navegador. Parece que IE estaba guardando en caché el certificado anterior. Al abrir los navegadores, el nuevo certificado entró en vigencia. ¡Problema resuelto!