c# - 使用 FlurlClient 的自定义 HttpClientHandler 不使用 ClientCertificate

标签 c# .net-core client-certificates x509certificate2 flurl

我需要在我的网络请求中添加一个客户端证书,并试图通过这种方式实现它: Stackoverflow

在此答案的末尾,介绍了“FlurlClient 方式”。使用和配置 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 是从链接的 StackOverflow 答案中复制的(但使用 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 返回一个 Url 对象,它只不过是一个字符串构建对象。它不保留对 FlurlClient 的引用。 (这允许 Flurl 作为独立于 Flurl.Http 的 URL 构建库存在。)
  • Url.AppendPathSegments 返回“this”Url
  • Url.GetJsonAsync 是一种扩展方法,它首先创建一个 FlurlClient,然后将其与当前 Url 一起使用以进行 HTTP 调用。

如您所见,您在该流程的第 1 步中丢失了对 fc 的引用。 2 种可能的解决方案:

<强>1。首先构建 URL,然后流畅地添加 HTTP 位:

url
    .AppendPathSegments(...)
    .ConfigureClient(...)
    .WithHeaders(...)
    .GetJsonAsync();

<强>2。或者,如果您想重用 FlurlClient,请使用 WithClient 将其“附加”到 URL:

var fc = new FlurlClient()
    .ConfigureClient(...)
    .WithHeaders(...);

url
    .AppendPathSegments(...)
    .WithClient(fc)
    .GetJsonAsync();

关于c# - 使用 FlurlClient 的自定义 HttpClientHandler 不使用 ClientCertificate,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45060556/

相关文章:

.net-core - 使用 DotNetRDf.Query.FullText 创建 Lucene 索引器时出现异常

c# - 从应用程序设置中定义的 KeyVault 检索 secret

mysql - 在 go 中使用 ssl 和证书连接到 mysql/mariadb

c# - 在 .net 中通过 https/http 获取 FileAttributes

c# - 无法将自定义 ActiveX 控件添加到 .NET Core WinForms 应用程序,但 .NET Framework 应用程序工作正常

c# - 向 ASP.NET MVC4 项目添加类

android - Linphone Android : Remote Provisioning Client-Side TLS Certificates

ssl - https 客户端证书注销/重新登录

c# - 在 WPF 3D 中旋转 360 度

c# - 我怎样才能做出无条件断言