使用FlurlClient的自定义HttpClientHandler不使用ClientCertificate

时间:2017-07-12 14:29:54

标签: 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
}

从链接的StackOverflow答案中复制X509HttpFactory(但使用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 个答案:

答案 0 :(得分:4)

这一切都归结为你所称的命令:

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