使用 HttpClientFactory .net Core 2.1 对每个请求进行身份验证
Authentication per request using HttpClientFactory .net Core 2.1
我应该如何使用 HttpClientFactory 来 return 其 uri 和凭据在调用时确定的 HttpClient 实例?
现有代码如下所示:
var httpClientHandler = new HttpClientHandler()
{
Credentials = new NetworkCredential(userName, password),
};
HttpClient client = new HttpClient(httpClientHandler);
client.BaseAddress = new Uri(_appSetting.ServiceURI);
启动中的 ConfigureServices 方法 class
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("", ""),
};
});
你的控制器看起来像这样
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);
}
使用 httpclientfactory 时,您可能无法在 运行 时设置网络凭据,可能需要在启动时设置 class。您可以在此处找到有关此问题的信息。
https://github.com/aspnet/HttpClientFactory/issues/71
如果您使用 .net 依赖注入,您可以将一个 class 的配置添加到您的设置代码中:
services
.AddTransient<DataLoader>()
.AddHttpClient<DataLoader>().ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler()
{
Credentials = new NetworkCredential(LoadUsernameFromConfig(), LoadPasswordFromSecureLocation())
});
现在添加 DI 将使用此凭证的 HttpClient
注入 DataLoader
class:
public class DataLoader
{
private readonly HttpClient httpClient;
public DataLoader(HttpClient httpClient)
{
this.httpClient = httpClient;
}
public async Task LoadData(string tableName)
{
var json = await httpClient.GetStringAsync("https://protected.example.com/json");
...
}
}
(如果我没有 Imran Arshad 的答案,我将无法想出这段代码:谢谢!)
您可以像这样创建身份验证委托处理程序:
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);
}
}
然后将其添加到 HttpClient 构建器和 DI 容器中:
services
.AddTransient<AuthenticationHttpMessageHandler>()
.AddHttpClient("MyClient")
.AddHttpMessageHandler<AuthenticationHttpMessageHandler>();
然后使用 IHttpClientFactory 创建 HttpClient 实例。
这种方法的核心优势是您可以清楚地分离关注点。您不接触主处理程序,不手动管理客户端创建,您利用工厂及其构建器扩展方法的全部功能。身份验证处理程序自然会注入到管道中,并为每个请求添加授权。可以通过抽象出凭据源并使处理程序依赖于某些 IAuthenticationProvider 抽象来进一步增强此处理程序,这将只需要 DI 配置而不涉及 HttpClient 配置代码。
我应该如何使用 HttpClientFactory 来 return 其 uri 和凭据在调用时确定的 HttpClient 实例?
现有代码如下所示:
var httpClientHandler = new HttpClientHandler()
{
Credentials = new NetworkCredential(userName, password),
};
HttpClient client = new HttpClient(httpClientHandler);
client.BaseAddress = new Uri(_appSetting.ServiceURI);
启动中的 ConfigureServices 方法 class
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("", ""),
};
});
你的控制器看起来像这样
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);
}
使用 httpclientfactory 时,您可能无法在 运行 时设置网络凭据,可能需要在启动时设置 class。您可以在此处找到有关此问题的信息。 https://github.com/aspnet/HttpClientFactory/issues/71
如果您使用 .net 依赖注入,您可以将一个 class 的配置添加到您的设置代码中:
services
.AddTransient<DataLoader>()
.AddHttpClient<DataLoader>().ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler()
{
Credentials = new NetworkCredential(LoadUsernameFromConfig(), LoadPasswordFromSecureLocation())
});
现在添加 DI 将使用此凭证的 HttpClient
注入 DataLoader
class:
public class DataLoader
{
private readonly HttpClient httpClient;
public DataLoader(HttpClient httpClient)
{
this.httpClient = httpClient;
}
public async Task LoadData(string tableName)
{
var json = await httpClient.GetStringAsync("https://protected.example.com/json");
...
}
}
(如果我没有 Imran Arshad 的答案,我将无法想出这段代码:谢谢!)
您可以像这样创建身份验证委托处理程序:
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);
}
}
然后将其添加到 HttpClient 构建器和 DI 容器中:
services
.AddTransient<AuthenticationHttpMessageHandler>()
.AddHttpClient("MyClient")
.AddHttpMessageHandler<AuthenticationHttpMessageHandler>();
然后使用 IHttpClientFactory 创建 HttpClient 实例。
这种方法的核心优势是您可以清楚地分离关注点。您不接触主处理程序,不手动管理客户端创建,您利用工厂及其构建器扩展方法的全部功能。身份验证处理程序自然会注入到管道中,并为每个请求添加授权。可以通过抽象出凭据源并使处理程序依赖于某些 IAuthenticationProvider 抽象来进一步增强此处理程序,这将只需要 DI 配置而不涉及 HttpClient 配置代码。