2010-01-14 22 views
61

So che è piuttosto semplice aggiungere un certificato a una HttpWebRequest. Tuttavia, non ho trovato un modo per fare l'equivalente utilizzando WebClient. In linea di principio, desidero inviare un POST con un certificato specifico utilizzando WebClient.Come si può aggiungere un certificato a WebClient (C#)?

Come si raggiungere questo codice esatto utilizzando WebClient:

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

risposta

72

Devi sottoclasse e sovrascrivere una o più funzioni.

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

Grazie, ha funzionato alla grande. – Andrew

+0

Fantastico! State cercando di capire come fare questo per troppo lungo tempo – RandomInsano

4

Proprio sottoclasse WebClient, aggiungere la tua ClientCertificates proprietà e l'override del metodo WebClient.GetWebRequest(System.Uri). Non ho tempo per convertire questo per C# da VB ma dovrebbe essere abbastanza auto-esplicativo:

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

Una cosa interessante è accaduta quando un nuovo certificato è stato installato sui nostri front-end. Abbiamo iniziato a ricevere l'errore:

"La connessione sottostante è stata chiusa: Impossibile stabilire la relazione di trust per il canale protetto SSL/TLS .; La connessione sottostante è stata chiusa: Impossibile stabilire la relazione di trust per il canale protetto SSL/TLS. ;"

Abbiamo risolto l'errore visitando ciascun front-end e aprendo il browser. Sembra che IE stia memorizzando nella cache il vecchio certificato. Aprendo i browser, il nuovo certificato ha avuto effetto. Problema risolto!

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

Ora puoi con certificato autofirmato! ("La connessione sottostante chiusa: Impossibile stabilire una relazione di fiducia per la SSL/TLS canale sicuro .; La connessione sottostante chiusa: Impossibile stabilire una relazione di fiducia per la SSL/TLS canale sicuro .;")

 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

Se aggiungete il certificato al webRequest.ClientCertificates allora non è più necessario sovrascrivere il ServerCertificateValidationCallback, che è un'impostazione globale, e quindi si sta influenzando tutto –

+0

se si avere questo messaggio di esecuzione 'La connessione sottostante è stata chiusa: Impossibile stabilire la relazione di trust per il canale protetto SSL/TLS 'aggiungere il seguente' ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 | SecurityProtocolType.Ssl3; ' – Fourat