Обойти неверный сертификат 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: удаленный сертификат недействителен в соответствии с процедурой проверки

К счастью, сертификат был создан с использованием цепочки. Конечно, вы всегда можете игнорировать это решение и использовать вышеуказанные решения.

Итак, вот мое решение:

  1. Я сохранил сертификат с помощью Chrome на своем компьютере в формате P7B.

  2. Преобразуйте сертификат в формат PEM с помощью этой команды:

    openssl pkcs7 -inform DER -outform PEM -in.p7b -print_certs> ca_bundle.crt

  3. Откройте файл ca_bundle.crt и удалите все записи Subject, оставив чистый файл. Пример ниже:

    ----- НАЧАТЬ СЕРТИФИКАТ -----
    _BASE64 DATA_
    ----- КОНЕЦ СЕРТИФИКАТА -----
    ----- НАЧАТЬ СЕРТИФИКАТ -----
    _BASE64 DATA_
    ----- КОНЕЦ СЕРТИФИКАТА -----
    ----- НАЧАТЬ СЕРТИФИКАТ -----
    _BASE64 DATA_
    ----- КОНЕЦ СЕРТИФИКАТА -----
  1. Поместите эти строки в 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-сертификаты

  1. В приложении:

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 с испорченным сертификатом.

Другие вопросы по тегам