使用 HttpClientFactory .net Core 2.1 对每个请求进行身份验证

Sim*_*n H 4 c# .net-core httpclientfactory

我应该如何使用 HttpClientFactory 返回 HttpClient 的实例,其 uri 和凭据是在调用时确定的?

现有代码如下所示:

var httpClientHandler = new HttpClientHandler()
    {
        Credentials = new NetworkCredential(userName, password),
    };
HttpClient client = new HttpClient(httpClientHandler);
client.BaseAddress = new Uri(_appSetting.ServiceURI);
Run Code Online (Sandbox Code Playgroud)

Imr*_*had 7

启动类中的 ConfigureServices 方法

             services.AddHttpClient("github", c =>
            {
                //c.BaseAddress = new Uri("https://api.github.com/");
                c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
                c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");
                
            }).ConfigurePrimaryHttpMessageHandler(() =>
            {
                return new HttpClientHandler()
                {
                    UseDefaultCredentials = true,
                    Credentials = new NetworkCredential("", ""),
                };
            });
Run Code Online (Sandbox Code Playgroud)

你的控制器看起来像这样

 private readonly IHttpClientFactory _httpClientFactory;

        public DataProController(IHttpClientFactory httpClientFactory)
        {
            _httpClientFactory = httpClientFactory;
        }

        [HttpGet]
        public async Task<ActionResult> Get()
        {            
            var client = _httpClientFactory.CreateClient("github");
            
            client.BaseAddress = new Uri("https://api.github.com/");

            string result = await client.GetStringAsync("/");
            return Ok(result);
        }
Run Code Online (Sandbox Code Playgroud)

使用 httpclientfactory 时,您可能无法在运行时设置网络凭据,可能需要在启动类中进行设置。您可以在此处找到有关此问题的信息。 https://github.com/aspnet/HttpClientFactory/issues/71


sic*_*ich 5

您可以像这样创建一个身份验证委托处理程序:

public class AuthenticationHttpMessageHandler : DelegatingHandler
    {
        protected override async Task<HttpResponseMessage> SendAsync(
            HttpRequestMessage request,
            CancellationToken cancellationToken)
        {
            // Get the token or other type of credentials here
            // string scheme = ... // E.g. "Bearer", "Basic" etc.
            // string credentials = ... // E.g. formatted token, user/password etc.

            request.Headers.Authorization =
                new AuthenticationHeaderValue(scheme, credentials);

            return await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
        }
    }
Run Code Online (Sandbox Code Playgroud)

然后将其添加到 HttpClient 构建器和 DI 容器中:

 services
     .AddTransient<AuthenticationHttpMessageHandler>()
     .AddHttpClient("MyClient")
     .AddHttpMessageHandler<AuthenticationHttpMessageHandler>();
Run Code Online (Sandbox Code Playgroud)

然后使用 IHttpClientFactory 创建 HttpClient 实例。

这种方法的核心优势是您可以清楚地分离关注点。您无需接触主处理程序,无需手动管理客户端创建,而是利用了工厂及其构建器扩展方法的全部功能。身份验证处理程序自然地注入管道中,并为每个请求添加授权。这个处理程序可以通过抽象出凭证的来源来进一步增强,并使处理程序依赖于一些 IAuthenticationProvider 抽象,这将只需要 DI 配置而不涉及 HttpClient 配置代码。

  • @kerzerk 是的。在这种情况下,您应该仅将处理程序添加到服务集合 (services.AddTransient&lt;AuthenticationHttpMessageHandler&gt;()) 一次,并且需要为每个客户端指定要添加到客户端的处理程序 (.AddHttpMessageHandler&lt;AuthenticationHttpMessageHandler&gt;())。 (2认同)