79

I know it is pretty simple to add a certificate to a HttpWebRequest. However, I have not found a way to do the equivalent using WebClient. Basically, I want to send out a POST with a specific certificate using WebClient.

How would you accomplish this exact code using WebClient:

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

4 Answers 4

103

You must subclass and override one or more functions.

class MyWebClient : WebClient { protected override WebRequest GetWebRequest(Uri address) { HttpWebRequest request = (HttpWebRequest)base.GetWebRequest(address); request.ClientCertificates.Add(new X509Certificate()); return request; } } 
Sign up to request clarification or add additional context in comments.

1 Comment

Awesome! Been trying to figure out how to do this for far far too long
12
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; } } 

Now you can with self signed cert ! ("The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.; The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.;")

 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 Comments

If you add the certificate to the webRequest.ClientCertificates then you no longer need to override the ServerCertificateValidationCallback , which is a global setting, and thus you are affecting everything
if you have this exeception message The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel add the this ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 | SecurityProtocolType.Ssl3;
5

An interesting thing happened when a new certificate was installed on our front-ends. We started getting the error:

"The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.; The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.;"

We took care of the error by going to each front-end and opening the browser. It seems that IE was caching the old certificate. By opening the browsers, the new certificate took effect. Problem Solved!

Comments

4

Just subclass WebClient, add your own ClientCertificates property and override the WebClient.GetWebRequest(System.Uri) method. I don't have time to convert this to C# from VB but it should be fairly self-explanatory:

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 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.