c# - La solicitud HTTPS falla al usar HttpClient
asp.net-core .net-core (1)
De acuerdo con esta publicación SO , debe habilitar TLS1.2 con ServicePointManager.
System.Net.ServicePointManager.SecurityProtocol =
SecurityProtocolType.Tls12 |
SecurityProtocolType.Tls11 |
SecurityProtocolType.Tls; // comparable to modern browsers
También cabe destacar que la documentación de MSDN para la propiedad ServicePointManager.SecurityProtocols realiza esta declaración:
.NET Framework 4.6 incluye una nueva característica de seguridad que bloquea algoritmos inseguros de cifrado y hash para las conexiones.
lo que sugiere que alguna forma de bloque SHA1 podría estar en su lugar.
Estoy usando el siguiente código y obtengo la excepción HttpRequestException
:
using (var handler = new HttpClientHandler())
{
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
handler.SslProtocols = SslProtocols.Tls12;
handler.ClientCertificates.Add(new X509Certificate2(@"C:/certificates/cert.pfx"));
// I also tried to add another certificates that was provided to https access
// by administrators of the site, but it still doesn''t work.
//handler.ClientCertificates.Add(new X509Certificate2(@"C:/certificates/cert.crt"));
//handler.ClientCertificates.Add(new X509Certificate2(@"C:/certificates/cert_ca.crt"));
using (var client = new HttpClient(handler))
{
var response = client.GetAsync("https://someurl.com/api.php?arg1=some&arg2=test").GetAwaiter().GetResult();
// ^ HttpRequestException: An error occurred while sending the request.
}
}
La excepción:
WinHttpException: A security error occurred
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.ConfiguredTaskAwaitable+ConfiguredTaskAwaiter.GetResult()
System.Net.Http.WinHttpHandler+<StartRequest>d__105.MoveNext()
HttpRequestException: An error occurred while sending the request.
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.ConfiguredTaskAwaitable+ConfiguredTaskAwaiter.GetResult()
System.Net.Http.HttpClient+<FinishSendAsync>d__58.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
MyApp.Web.Controllers.HomeController.Test() in HomeController.cs
var response = client.GetAsync("https://someurl.com/api.php?arg1=some&arg2=test").GetAwaiter().GetResult();
lambda_method(Closure , object , Object[] )
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker+<InvokeActionMethodAsync>d__27.MoveNext()
También traté de exportar los mismos certificados al Windows Certificate Store y usarlo a través de Google Chrome y funciona bien (el navegador me pidió que confirmara el certificado instalado y luego cargó el recurso).
¿Por qué no está funcionando en mi código?
ACTUALIZADO
También traté de agregar devolución de llamada para validar el certificado:
handler.ServerCertificateCustomValidationCallback = (message, certificate2, arg3, arg4) =>
{
// I set a breakpoint to this point but it is not catched.
return true;
};
ACTUALIZADO2
El certificado se usa SHA-1. Neil Moss se menciona en los comentarios que el soporte para certificaciones SHA1 está siendo retirado . Si es la verdadera razón por la que no funciona, ¿hay alguna solución para ello?
SOLUCIÓN
Gracias Neil Moss por la solución. Propuso usar la bandera Tls para el protocolo SSL.
handler.SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls;
Pero también requirió lo siguiente:
handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true;
Después de que agregué este, funciona bien.