Обойти неверный сертификат SSL в ядре.net
Я работаю над проектом, который должен подключиться к сайту https. Каждый раз, когда я подключаюсь, мой код генерирует исключение, потому что сертификат этого сайта происходит от ненадежного сайта. Есть ли способ обойти проверку сертификата в.net core http?
Я видел этот код из предыдущей версии.NET. Я думаю, мне просто нужно что-то подобное.
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
10 ответов
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
Вы можете переопределить проверку 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
потому что это общий объект, который может быть удален не сразу, и поэтому соединения останутся открытыми.
Решаю с этим:
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
};
Это на самом деле легко
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 я получил такую ошибку:
System.Security.Authentication.AuthenticationException: удаленный сертификат недействителен в соответствии с процедурой проверки
К счастью, сертификат был создан с использованием цепочки. Конечно, вы всегда можете игнорировать это решение и использовать вышеуказанные решения.
Итак, вот мое решение:
Я сохранил сертификат с помощью Chrome на своем компьютере в формате P7B.
Преобразуйте сертификат в формат PEM с помощью этой команды:
openssl pkcs7 -inform DER -outform PEM -in.p7b -print_certs> ca_bundle.crt
Откройте файл ca_bundle.crt и удалите все записи Subject, оставив чистый файл. Пример ниже:
----- НАЧАТЬ СЕРТИФИКАТ ----- _BASE64 DATA_ ----- КОНЕЦ СЕРТИФИКАТА ----- ----- НАЧАТЬ СЕРТИФИКАТ ----- _BASE64 DATA_ ----- КОНЕЦ СЕРТИФИКАТА ----- ----- НАЧАТЬ СЕРТИФИКАТ ----- _BASE64 DATA_ ----- КОНЕЦ СЕРТИФИКАТА -----
- Поместите эти строки в Dockerfile (на последних шагах):
# Обновление системы и установка curl и ca-сертификатов RUN apt-get update && apt-get install -y curl && apt-get install -y ca-сертификаты # Скопируйте ваш пакетный файл в доверенное хранилище системы COPY ./ca_bundle.crt /usr/local/share/ca-certificates/ca_bundle.crt # Во время сборки докера после этой строки вы получите такой вывод: 1 добавлено, 0 удалено; сделанный. RUN update-ca-сертификаты
- В приложении:
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); }
Разрешение всех сертификатов очень важно, но также может быть опасно. Если вы хотите разрешить только действительные сертификаты плюс некоторые определенные сертификаты, это можно сделать следующим образом.
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;
}
}
Первоисточник:
/questions/31773144/c-ignorirovat-oshibki-sertifikata/31773149#31773149
Во-первых, НЕ ИСПОЛЬЗУЙТЕ ЕГО В ПРОИЗВОДСТВЕ
Если вы используете промежуточное ПО 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);
Для .NET 6 вы можете настроить свой основной обработчик сообщений Http следующим образом:
services.AddHttpClient<ITodoListService, TodoListService>()
.ConfigurePrimaryHttpMessageHandler(() => {
var handler = new HttpClientHandler();
if (currentEnvironment.IsDevelopment()) {
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
}
return handler;
});
Да, открой свое приложение любому хакеру. Отличная идея. У меня уходит около двух минут на создание поддельного сертификата для любого сайта (со встроенной функциональностью MacOS X, скорее всего, доступной в Windows и Linux, а также в аналогичной форме). Перенаправление вашего сайта занимает много времени у хакера, но это не проблема.
Если у сайта есть испорченный или устаревший сертификат, то вы идете к администратору сайта, даете ему хороший удар и говорите ему, чтобы он исправил свой сайт. Ни при каких обстоятельствах вы не должны рассматривать использование https с испорченным сертификатом.