Пользовательский HttpClientHandler, использующий FlurlClient, не использует ClientCertificate
Мне нужно добавить сертификат клиента в мои веб-запросы и попытаться достичь его следующим образом: Stackru
В конце этого ответа представлен "FlurlClient way". Использование и настройка FlurlClient вместо глобальной конфигурации FlurlHttp. Я пробовал это, но это не сработало.
Я создал новое консольное приложение .NET Core, чтобы показать вам проблему:
static void Main(string[] args)
{
/****** NOT WORKING *******/
try
{
IFlurlClient fc1 = new FlurlClient(url)
.ConfigureClient(c => c.HttpClientFactory = new X509HttpFactory(GetCert()));
fc1.WithHeader("User-Agent", userAgent)
.WithHeader("Accept-Language", locale);
dynamic ret1 = fc1.Url.AppendPathSegments(pathSegments).GetJsonAsync()
.GetAwaiter().GetResult();
}
catch
{
// --> Exception: 403 FORBIDDEN
}
/****** NOT WORKING *******/
try
{
IFlurlClient fc2 = new FlurlClient(url);
fc2.Settings.HttpClientFactory = new X509HttpFactory(GetCert());
fc2.WithHeader("User-Agent", userAgent)
.WithHeader("Accept-Language", locale);
dynamic ret2 = fc2.Url.AppendPathSegments(pathSegments).GetJsonAsync()
.GetAwaiter().GetResult();
}
catch
{
// --> Exception: 403 FORBIDDEN
}
/****** WORKING *******/
FlurlHttp.Configure(c =>
{
c.HttpClientFactory = new X509HttpFactory(GetCert());
});
dynamic ret = url.AppendPathSegments(pathSegments).GetJsonAsync()
.GetAwaiter().GetResult();
// --> OK
}
X509HttpFactory
копируется из связанного ответа Stackru (но с использованием HttpClientHandler
вместо WebRequestHandler
):
public class X509HttpFactory : DefaultHttpClientFactory
{
private readonly X509Certificate2 _cert;
public X509HttpFactory(X509Certificate2 cert)
{
_cert = cert;
}
public override HttpMessageHandler CreateMessageHandler()
{
var handler = new HttpClientHandler();
handler.ClientCertificates.Add(_cert);
return handler;
}
}
Таким образом, использование глобальной конфигурации FlurlHttp работает, а настройка FlurlClient не работает. Зачем?
1 ответ
Это все сводится к тому, что вы называете вещи:
fc.Url
возвращаетUrl
объект, который немного больше чем строительная вещь. Это не держит ссылку наFlurlClient
, (Это позволяет Flurl существовать как библиотека создания URL-адресов независимо от Flurl.Http.)Url.AppendPathSegments
возвращает "это"Url
,Url.GetJsonAsync
это метод расширения, который сначала создаетFlurlClient
, а затем использует его с текущимUrl
сделать HTTP-вызов.
Итак, как вы можете видеть, вы потеряли свою ссылку на fc
на этапе 1 этого потока. 2 возможных решения:
1. Сначала создайте URL, затем плавно добавьте биты HTTP:
url
.AppendPathSegments(...)
.ConfigureClient(...)
.WithHeaders(...)
.GetJsonAsync();
2. ИЛИ, если вы хотите повторно использовать FlurlClient, "прикрепите" его к URL-адресу с помощью WithClient:
var fc = new FlurlClient()
.ConfigureClient(...)
.WithHeaders(...);
url
.AppendPathSegments(...)
.WithClient(fc)
.GetJsonAsync();