【发布时间】:2019-06-30 01:41:27
【问题描述】:
我正在使用httpClientFactory申请微信支付API,但是微信支付API需要证书。如何配置httpClientFactory 使用证书?
【问题讨论】:
标签: asp.net-core
我正在使用httpClientFactory申请微信支付API,但是微信支付API需要证书。如何配置httpClientFactory 使用证书?
【问题讨论】:
标签: asp.net-core
如果您查看 DI 中返回的 Default factory,它继承自两个接口,并且在注入时您选择只使用一个:
internal class DefaultHttpClientFactory : IHttpClientFactory, IHttpMessageHandlerFactory
知道了这一点,您可以采取一种偷偷摸摸的解决方法:
_handlerFactory = _clientFactory as IHttpMessageHandlerFactory;
现在,如果您查看处理程序工厂,它有一个方法CreateHandler,其字符串参数与CreateClient 方法相同。实际上,如果你查看CreateClient 的实现,你会发现它使用了这个方法,然后缓存了处理程序。
所以忘记启动:将您的客户端工厂转换为处理程序工厂,为您的特定用户创建处理程序,验证处理程序上的所有属性(比如那里的证书或者您是否需要添加它,因为它是一个新实例)和然后像往常一样拨打CreateClient。
编辑:在启动时,您可能仍需要添加 ConfigurePrimaryHttpMessageHandler 以实际创建一个 HttpClientHandler,因此您可能必须只注册一个名为 HttpClient 并交换证书。尽管如此,它仍然为您提供了拥有工厂的优势。
编辑2:知道处理程序在装饰器中被包裹了很多次,所以你需要深入挖掘。我使用的技巧是:
var handler = _handlerFactory.CreateHandler("customer");
while (handler as DelegatingHandler != null)
{
handler = (handler as DelegatingHandler).InnerHandler;
}
var clientHandler = handler as HttpClientHandler;
【讨论】:
首先,您需要注册HttpClient:
services.AddHttpClient("signed")
.ConfigurePrimaryMessageHandler(() =>
{
var handler = new HttpClientHandler();
var certificate = new X509Certificate2(filename: "foo.pfx", password: "123");
handler.ClientCertificateOptions = ClientCertificateOptions.Manual;
handler.ClientCertificates.Add(certificat);
});
在示例中,文件 foo.pfx 包含密码为 123 的证书。
签名是HttpClient的名称。
其次,您将调用IHttpClientFactory.CreateClient 来创建HttpClient 实例。
public class PayClient
{
private readonly IHttpClientFactory _httpClientFactory;
public PayClient(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}
public async Task SomePayMethodAsync()
{
using (httpClient = _httpClientFactory.CreateClient("signed"))
{
// use httpClient
}
}
}
您需要使用与CreateClient的参数相同的名称签名。
稍后更新
如果您使用许多证书编写 SAAS,您可以在每次需要时手动创建和配置 HttpClient。这是最简单的方法。
public class PayClient
{
private readonly ICurrentUserProvider _currentUserProvider;
public PayClient(ICurrentUserProvider _currentUserProvider)
{
_currentUserProvider = currentUserProvider;
}
private HttpClient CreateHttpClient()
{
var currentUser = _currentUserProvider.CurrentUser;
var filename = currentUser.CertificateFilename;
var password = currentUser.CertificatePassword;
var handler = new HttpClientHandler();
var certificate = new X509Certificate2(filename, password);
handler.ClientCertificateOptions = ClientCertificateOptions.Manual;
handler.ClientCertificates.Add(certificat);
return new HttpClient(handler);
}
public async Task SomePayMethodAsync()
{
using (httpClient = CreateHttpClient())
{
// use httpClient
}
}
}
【讨论】:
PayClient 这样的每个类都可以创建自己的HttpClient。通常你有一些远程服务的单一证书,所以这个决定应该有效。
https://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-3.1
services.AddHttpClient("configured-disable-automatic-cookies")
.ConfigurePrimaryHttpMessageHandler(() =>
{
return new SocketsHttpHandler()
{
UseCookies = false,
};
});
【讨论】: