Я работаю над проектом, которому необходимо подключиться к сайту https. Каждый раз, когда я подключаюсь, мой код выдает исключение, потому что сертификат этого сайта поступает с ненадежного сайта. Есть ли способ обойти проверку сертификата в .net core http?
Я видел этот код из предыдущей версии .NET. Думаю, мне просто нужно что-то вроде этого.
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
c#
ssl
asp.net-core
ssl-certificate
Рэмппи Дампи
источник
источник
Ответы:
ServicePointManager.ServerCertificateValidationCallback не поддерживается в .Net Core.
Текущая ситуация такова, что это будет новый метод ServerCertificateCustomValidationCallback для предстоящего контракта 4.1. * System.Net.Http (HttpClient). Команда .NET Core сейчас завершает работу над контрактом на версию 4.1. Вы можете прочитать об этом здесь, на github
Вы можете опробовать предварительную версию System.Net.Http 4.1, используя источники прямо здесь, в CoreFx или в ленте MYGET: https://dotnet.myget.org/gallery/dotnet-core
Текущее определение WinHttpHandler.ServerCertificateCustomValidationCallback на Github
источник
Обновить:
Как указано ниже, не все реализации поддерживают этот обратный вызов (например, платформы, такие как iOS). В этом случае, как говорится в документации , вы можете явно установить валидатор:
Это также работает для .NET Core 2.2, 3.0 и 3.1.
Старый ответ , с большим контролем, но может бросить
PlatformNotSupportedException
:Вы можете переопределить проверку сертификата SSL при HTTP-вызове с помощью анонимной функции обратного вызова, подобной этой
using (var httpClientHandler = new HttpClientHandler()) { httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; }; using (var client = new HttpClient(httpClientHandler)) { // Make your request... } }
Кроме того, я предлагаю использовать фабричный шаблон,
HttpClient
потому что это общий объект, который нельзя удалить немедленно, и поэтому соединения останутся открытыми .источник
HttpClient
свойство с именем,DangerousAcceptAnyServerCertificateValidator
которое позволяет сделать эту работу на MacOSX. Подробнее здесь - github.com/dotnet/corefx/pull/19908factory pattern
дляHttpClient
?GetHttpClient
метод возвращает сконфигурированноеHttpClient
и используйте его вusing
-блоке.Решаю с этим:
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);
источник
Пришел сюда в поисках ответа на ту же проблему, но я использую WCF для NET Core. Если вы находитесь в одной лодке, используйте:
client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication = new X509ServiceCertificateAuthentication() { CertificateValidationMode = X509CertificateValidationMode.None, RevocationMode = X509RevocationMode.NoCheck };
источник
В .NetCore вы можете добавить следующий фрагмент кода в методе настройки служб, я добавил проверку, чтобы убедиться, что мы передаем сертификат SSL только в среде разработки.
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; });
источник
Я столкнулся с той же проблемой при работе с самозаверяющими сертификатами и аутентификацией сертификатов клиента в контейнерах .NET Core 2.2 и Docker Linux. На моем компьютере с Windows все работало нормально, но в Docker я получил такую ошибку:
К счастью, сертификат был создан с помощью цепочки. Конечно, вы всегда можете проигнорировать это решение и использовать вышеуказанные решения.
Итак, вот мое решение:
Я сохранил сертификат с помощью Chrome на моем компьютере в формате P7B .
Преобразуйте сертификат в формат PEM с помощью этой команды:
openssl pkcs7 -inform DER -outform PEM -in <cert>.p7b -print_certs > ca_bundle.crt
Откройте файл ca_bundle.crt и удалите все записи темы, оставив чистый файл. Пример ниже:
# 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 };
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); }
источник
Во-первых, НЕ ИСПОЛЬЗУЙТЕ ЕГО В ПРОИЗВОДСТВЕ
Если вы используете промежуточное ПО AddHttpClient, это будет полезно. Я думаю, что это нужно для разработки, а не для производства. Пока вы не создадите действующий сертификат, вы можете использовать этот Func.
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; };
и примените это как
services.AddHttpClient<IMyClient, MyClient>(x => { x.BaseAddress = new Uri("https://localhost:5005"); }) .ConfigurePrimaryHttpMessageHandler(configureHandler);
источник
Разрешение всех сертификатов очень важно, но также может быть опасно. Если вы хотите разрешить только действительные сертификаты плюс некоторые определенные сертификаты, это можно сделать следующим образом.
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; } }
Первоисточник:
https://stackoverflow.com/a/44140506/3850405
источник