Estoy trabajando en un proyecto que necesita conectarse a un sitio https. Cada vez que me conecto, mi código genera una excepción porque el certificado de ese sitio proviene de un sitio que no es de confianza. ¿Hay alguna forma de omitir la verificación de certificados en .net core http?
Vi este código de la versión anterior de .NET. Supongo que solo necesito algo como esto.
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
c#
ssl
asp.net-core
ssl-certificate
Ramppy Dumppy
fuente
fuente
Respuestas:
ServicePointManager.ServerCertificateValidationCallback no es compatible con .Net Core.
La situación actual es que será un nuevo método ServerCertificateCustomValidationCallback para el próximo contrato 4.1. * System.Net.Http (HttpClient). El equipo de .NET Core está finalizando el contrato 4.1 ahora. Puedes leer sobre esto aquí en github
Puede probar la versión preliminar de System.Net.Http 4.1 utilizando las fuentes directamente aquí en CoreFx o en el feed de MYGET: https://dotnet.myget.org/gallery/dotnet-core
Definición actual de WinHttpHandler.ServerCertificateCustomValidationCallback en Github
fuente
Actualizar:
Como se menciona a continuación, no todas las implementaciones admiten esta devolución de llamada (es decir, plataformas como iOS). En este caso, como dicen los documentos , puede configurar el validador explícitamente:
Esto también funciona para .NET Core 2.2, 3.0 y 3.1
Respuesta anterior , con más control pero puede arrojar
PlatformNotSupportedException
:Puede anular la verificación del certificado SSL en una llamada HTTP con una función de devolución de llamada anónima como esta
using (var httpClientHandler = new HttpClientHandler()) { httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; }; using (var client = new HttpClient(httpClientHandler)) { // Make your request... } }
Además, sugiero usar un patrón de fábrica
HttpClient
porque es un objeto compartido que podría no eliminarse de inmediato y, por lo tanto, las conexiones permanecerán abiertas .fuente
HttpClient
propiedad llamadaDangerousAcceptAnyServerCertificateValidator
que proporciona una manera de hacer que esto funcione en MacOSX. Más información aquí - github.com/dotnet/corefx/pull/19908factory pattern
paraHttpClient
?GetHttpClient
Método devuelve lo configuradoHttpClient
y lo usa dentro de unusing
-bloque.Resuelvo con esto:
Startup.cs
public void ConfigureServices(IServiceCollection services) { services.AddHttpClient("HttpClientWithSSLUntrusted").ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler { ClientCertificateOptions = ClientCertificateOption.Manual, ServerCertificateCustomValidationCallback = (httpRequestMessage, cert, cetChain, policyErrors) => { return true; } });
YourService.cs
public UserService(IHttpClientFactory clientFactory, IOptions<AppSettings> appSettings) { _appSettings = appSettings.Value; _clientFactory = clientFactory; } var request = new HttpRequestMessage(... var client = _clientFactory.CreateClient("HttpClientWithSSLUntrusted"); HttpResponseMessage response = await client.SendAsync(request);
fuente
Vine aquí buscando una respuesta al mismo problema, pero estoy usando WCF para NET Core. Si estás en el mismo barco, usa:
client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication = new X509ServiceCertificateAuthentication() { CertificateValidationMode = X509CertificateValidationMode.None, RevocationMode = X509RevocationMode.NoCheck };
fuente
En .NetCore, puede agregar el siguiente fragmento de código en el método de configuración de servicios, agregué una verificación para asegurarme solo de que pasamos el certificado SSL solo en el entorno de desarrollo
services.AddHttpClient("HttpClientName", client => { // code to configure headers etc.. }).ConfigurePrimaryHttpMessageHandler(() => { var handler = new HttpClientHandler(); if (hostingEnvironment.IsDevelopment()) { handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; }; } return handler; });
fuente
Me enfrenté al mismo problema cuando trabajaba con certificados autofirmados y autenticación de certificados de cliente en contenedores .NET Core 2.2 y Docker Linux. Todo funcionó bien en mi máquina de Windows de desarrollo, pero en Docker obtuve tal error:
Afortunadamente, el certificado se generó mediante una cadena. Por supuesto, siempre puede ignorar esta solución y utilizar las soluciones anteriores.
Entonces aquí está mi solución:
Guardé el certificado usando Chrome en mi computadora en formato P7B .
Convierta el certificado a formato PEM usando este comando:
openssl pkcs7 -inform DER -outform PEM -in <cert>.p7b -print_certs > ca_bundle.crt
Abra el archivo ca_bundle.crt y elimine todas las grabaciones del sujeto, dejando un archivo limpio. Ejemplo a continuación:
# Update system and install curl and ca-certificates RUN apt-get update && apt-get install -y curl && apt-get install -y ca-certificates # Copy your bundle file to the system trusted storage COPY ./ca_bundle.crt /usr/local/share/ca-certificates/ca_bundle.crt # During docker build, after this line you will get such output: 1 added, 0 removed; done. RUN update-ca-certificates
var address = new EndpointAddress("https://serviceUrl"); var binding = new BasicHttpsBinding { CloseTimeout = new TimeSpan(0, 1, 0), OpenTimeout = new TimeSpan(0, 1, 0), ReceiveTimeout = new TimeSpan(0, 1, 0), SendTimeout = new TimeSpan(0, 1, 0), MaxBufferPoolSize = 524288, MaxBufferSize = 65536, MaxReceivedMessageSize = 65536, TextEncoding = Encoding.UTF8, TransferMode = TransferMode.Buffered, UseDefaultWebProxy = true, AllowCookies = false, BypassProxyOnLocal = false, ReaderQuotas = XmlDictionaryReaderQuotas.Max, Security = { Mode = BasicHttpsSecurityMode.Transport, Transport = new HttpTransportSecurity { ClientCredentialType = HttpClientCredentialType.Certificate, ProxyCredentialType = HttpProxyCredentialType.None } } }; var client = new MyWSClient(binding, address); client.ClientCredentials.ClientCertificate.Certificate = GetClientCertificate("clientCert.pfx", "passwordForClientCert"); // Client certs must be installed client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication = new X509ServiceCertificateAuthentication { CertificateValidationMode = X509CertificateValidationMode.ChainTrust, TrustedStoreLocation = StoreLocation.LocalMachine, RevocationMode = X509RevocationMode.NoCheck };
Método GetClientCertificate:
private static X509Certificate2 GetClientCertificate(string clientCertName, string password) { //Create X509Certificate2 object from .pfx file byte[] rawData = null; using (var f = new FileStream(Path.Combine(AppContext.BaseDirectory, clientCertName), FileMode.Open, FileAccess.Read)) { var size = (int)f.Length; var rawData = new byte[size]; f.Read(rawData, 0, size); f.Close(); } return new X509Certificate2(rawData, password); }
fuente
En primer lugar, NO LO USE EN PRODUCCIÓN
Si está utilizando el middleware AddHttpClient, esto será útil. Creo que es necesario para el desarrollo, no para la producción. Hasta que cree un certificado válido, puede utilizar esta función.
Func<HttpMessageHandler> configureHandler = () => { var bypassCertValidation = Configuration.GetValue<bool>("BypassRemoteCertificateValidation"); var handler = new HttpClientHandler(); //!DO NOT DO IT IN PRODUCTION!! GO AND CREATE VALID CERTIFICATE! if (bypassCertValidation) { handler.ServerCertificateCustomValidationCallback = (httpRequestMessage, x509Certificate2, x509Chain, sslPolicyErrors) => { return true; }; } return handler; };
y aplicarlo como
services.AddHttpClient<IMyClient, MyClient>(x => { x.BaseAddress = new Uri("https://localhost:5005"); }) .ConfigurePrimaryHttpMessageHandler(configureHandler);
fuente
Permitir todos los certificados es muy poderoso, pero también puede ser peligroso. Si solo desea permitir certificados válidos más algunos certificados determinados, puede hacerlo así.
using (var httpClientHandler = new HttpClientHandler()) { httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, sslPolicyErrors) => { if (sslPolicyErrors == SslPolicyErrors.None) { return true; //Is valid } if (cert.GetCertHashString() == "99E92D8447AEF30483B1D7527812C9B7B3A915A7") { return true; } return false; }; using (var httpClient = new HttpClient(httpClientHandler)) { var httpResponse = httpClient.GetAsync("https://example.com").Result; } }
Fuente original:
https://stackoverflow.com/a/44140506/3850405
fuente