¿Cómo se puede agregar un certificado al cliente Web (C #)?
-
20-09-2019 - |
Pregunta
Sé que es bastante simple para agregar un certificado a un HttpWebRequest. Sin embargo, no he encontrado una manera de hacer el equivalente utilizando WebClient. Básicamente, quiero enviar un POST con un certificado específico utilizando WebClient.
¿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
Solución
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;
}
}
Otros consejos
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 se puede cert con 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 los 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));
Sólo WebClient
subclase, añadir su propiedad ClientCertificates
y reemplazar 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
Una cosa interesante ocurrió cuando un nuevo certificado se ha instalado en nuestras front-end. Empezamos a recibir el error:
"La conexión subyacente se cerró: No se pudo establecer una relación de confianza para el SSL / TLS canal seguro .; la conexión subyacente se cerró:. No se pudo establecer relación de confianza para los SSL / TLS canal seguro;"
Nos ocupamos del error yendo a cada front-end y abrir el navegador. Parece que el almacenamiento en caché de IE fue el antiguo certificado. Con la apertura de los navegadores, el nuevo certificado entró en vigor. Problema resuelto!