HTTPS-запрос не выполняется с помощью HttpClient



Я использую следующий код и получаю HttpRequestException исключение:



using (var handler = new HttpClientHandler())
{
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
handler.SslProtocols = SslProtocols.Tls12;
handler.ClientCertificates.Add(new X509Certificate2(@"C:certificatescert.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:certificatescert.crt"));
//handler.ClientCertificates.Add(new X509Certificate2(@"C:certificatescert_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.
}
}


Исключение:



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()


Я также попытался экспортировать те же сертификаты в хранилище сертификатов Windows и использовать его через Google Chrome, и он работает нормально (браузер попросил меня подтвердить установленный сертификат, а затем загрузил ресурс).



Почему он не работает в моем коде?



Обновлено



Я также попытался добавить обратный вызов для проверки сертификат:



handler.ServerCertificateCustomValidationCallback = (message, certificate2, arg3, arg4) =>
{
// I set a breakpoint to this point but it is not catched.
return true;
};


UPDATED2



Сертификат используется SHA-1. Нил Мосс упоминается в комментариях, чтоподдержка сертификатов SHA1 прекращается .
Если это реальная причина, почему он не работает, есть ли обходной путь для него?



Решение



Спасибо Нейлу Моссу за решение. Он предложил использовать флаг Tls для протокола SSL.



handler.SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls;


Но для этого также требовалось следующее:



handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true;


После того, как я добавил Этот, он работает хорошо.

674   2  

2 ответов:

Согласно этому сообщению SO, Вы должны включить TLS1.2 с ServicePointManager.

System.Net.ServicePointManager.SecurityProtocol =
    SecurityProtocolType.Tls12 | 
    SecurityProtocolType.Tls11 | 
    SecurityProtocolType.Tls; // comparable to modern browsers

Также заслуживает внимания документацияMSDN для ServicePointManager.Свойство SecurityProtocols делает следующее утверждение:

Платформа .NET Framework 4.6 включает новую функцию безопасности, которая блокирует небезопасные алгоритмы шифрования и хэширования соединений.

, что предполагает, что некоторая форма блока SHA1 может быть на месте.

Это был очень полезный документ. Ибо ASP.NET ядро 2.0, ответ был применен следующим образом (результат был успешным):

using (var handler = new HttpClientHandler())
{
    handler.ServerCertificateCustomValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;
    handler.SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls;
    using (HttpClient client = new HttpClient(handler))
    {
        string requestObjJson = requestObj.ToJson();
        var address = new Uri($"https://yourcompany.com/");
        string token = GetToken();
        client.BaseAddress = address;
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
        var contentData = new StringContent(requestObjJson, System.Text.Encoding.UTF8, "application/json");
        using (var response = await client.PostAsync("yourcompany/new-employee", contentData))
        {
            var content = response.Content.ReadAsStringAsync();
            var taskResult = content.Result;
            JObject resultObj = JObject.Parse(taskResult);
            return resultObj;
        }
    }
}

Comments

    Ничего не найдено.