2010-01-14 18 views
61

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 se puede agregar un Certificado a WebClient (C#)?

¿Cómo lograr esto usando código exacto cliente Web:

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

Respuesta

72

Debe subclase 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; 
    } 
} 
+0

Gracias, esto funcionó muy bien. – Andrew

+0

¡Impresionante! He estado intentando descubrir cómo hacerlo por demasiado tiempo – RandomInsano

4

Sólo subclase WebClient, añadir su ClientCertificates propiedad y anular el método WebClient.GetWebRequest(System.Uri). No tengo tiempo para convertir esto en C# desde VB pero debe ser bastante explica por sí mismo:

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 
4

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

"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 SSL/TLS seguro. ; "

Hemos solucionado el 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!

9
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 relación de confianza para el canal seguro SSL/TLS .; la conexión subyacente se cerró: No se pudo establecer relación de confianza para el SSL/TLS canal seguro .;")

 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)); 
+2

Si agrega el certificado a webRequest.ClientCertificates, ya no necesita reemplazar el ServerCertificateValidationCallback, que es una configuración global, y por lo tanto está afectando todo –

+0

si tener este mensaje de excepción 'La conexión subyacente se cerró: no se pudo establecer una relación de confianza para el canal seguro SSL/TLS' agregue esto' ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 | SecurityProtocolType.Ssl3; ' – Fourat

Cuestiones relacionadas