我读过很多文章,但发现有关这部分流程的信息很少,所以我猜它可能非常简单,指南中从未详细说明过,但我仍然不知道!
问题是这些文档确实分散在各处,因此很难全面了解所有最佳实践。我正在计划一个关于“现代 HTTP API 客户端”的博客系列,该系列将收集所有这些最佳实践。
首先,我推荐你使用HttpClientFactory而不是新建一个HttpClient https://learn.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests#issues-with-the-original-httpclient-class-available-in-net-core.
接下来,添加授权标头是 IMO 最好通过挂钩来完成HttpClient
的消息处理程序管道。基本的不记名令牌身份验证助手可能如下所示:
public sealed class BackendApiAuthenticationHttpClientHandler : DelegatingHandler
{
private readonly IHttpContextAccessor _accessor;
public BackendApiAuthenticationHttpClientHandler(IHttpContextAccessor accessor)
{
_accessor = accessor;
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var expat = await _accessor.HttpContext.GetTokenAsync("expires_at");
var dataExp = DateTime.Parse(expat, null, DateTimeStyles.RoundtripKind);
if ((dataExp - DateTime.Now).TotalMinutes < 10)
{
//SNIP GETTING A NEW TOKEN IF ITS ABOUT TO EXPIRE
}
var token = await _accessor.HttpContext.GetTokenAsync("access_token");
// Use the token to make the call.
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
return await base.SendAsync(request, cancellationToken);
}
}
这可以通过 DI 连接:
services.AddTransient<BackendApiAuthenticationHttpClientHandler>();
services.AddHttpClient<MyController>()
.ConfigureHttpClient((provider, c) => c.BaseAddress = new Uri("https://localhost:44308/api"))
.AddHttpMessageHandler<BackendApiAuthenticationHttpClientHandler>();
然后你可以注入一个HttpClient
进入你的MyController
,它会神奇地使用身份验证令牌:
// _client is an HttpClient, initialized in the constructor
string testUri = "TestItems";
var response = await _client.GetAsync(testUri, HttpCompletionOption.ResponseHeadersRead);
var data = await response.Content.ReadAsStringAsync();
GetFromApiViewModel vm = new GetFromApiViewModel()
{
Output = data
};
return View(vm);
这种模式乍一看似乎很复杂,但它将“我如何调用这个 API”逻辑与“这个操作在做什么”逻辑分开。通过 Polly,通过重试/断路器等更容易扩展。