使用 FlurlClient 的自定义 HttpClientHandler 不使用 ClientCertificate
Custom HttpClientHandler using FlurlClient doesn't use ClientCertificate
我需要将客户端证书添加到我的网络请求中,并尝试以这种方式实现:
在这个答案的最后出现 "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
是从链接的 Whosebug 答案中复制的(但使用 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 是无效的。为什么?
这一切都取决于您调用事物的顺序:
fc.Url
returns 一个 Url
对象,它只不过是一个字符串构建的东西。它不保留对 FlurlClient
的引用。 (这允许 Flurl 作为独立于 Flurl.Http 的 URL 构建库存在。)
Url.AppendPathSegments
returns "this" Url
.
Url.GetJsonAsync
是一种扩展方法,它首先创建一个 FlurlClient
,然后将其与当前的 Url
一起使用以进行 HTTP 调用。
如您所见,您在该流程的第 1 步中丢失了对 fc
的引用。 2 种可能的解决方案:
1.首先构建 URL,然后流畅地添加 HTTP 位:
url
.AppendPathSegments(...)
.ConfigureClient(...)
.WithHeaders(...)
.GetJsonAsync();
2。或者,如果你想重用 FlurlClient,"attach" 它到 URL 使用 WithClient:
var fc = new FlurlClient()
.ConfigureClient(...)
.WithHeaders(...);
url
.AppendPathSegments(...)
.WithClient(fc)
.GetJsonAsync();
我需要将客户端证书添加到我的网络请求中,并尝试以这种方式实现:
在这个答案的最后出现 "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
是从链接的 Whosebug 答案中复制的(但使用 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 是无效的。为什么?
这一切都取决于您调用事物的顺序:
fc.Url
returns 一个Url
对象,它只不过是一个字符串构建的东西。它不保留对FlurlClient
的引用。 (这允许 Flurl 作为独立于 Flurl.Http 的 URL 构建库存在。)Url.AppendPathSegments
returns "this"Url
.Url.GetJsonAsync
是一种扩展方法,它首先创建一个FlurlClient
,然后将其与当前的Url
一起使用以进行 HTTP 调用。
如您所见,您在该流程的第 1 步中丢失了对 fc
的引用。 2 种可能的解决方案:
1.首先构建 URL,然后流畅地添加 HTTP 位:
url
.AppendPathSegments(...)
.ConfigureClient(...)
.WithHeaders(...)
.GetJsonAsync();
2。或者,如果你想重用 FlurlClient,"attach" 它到 URL 使用 WithClient:
var fc = new FlurlClient()
.ConfigureClient(...)
.WithHeaders(...);
url
.AppendPathSegments(...)
.WithClient(fc)
.GetJsonAsync();