我正在尝试将一个使用 Asp.Net Core Identity、Identity Server 4 和 Web API 项目的小项目放在一起。
我已经使用 IdS4 正确验证了我的 MVC 项目,从中我得到了一个 JWT,然后我可以将它添加到我的 Web API 项目的请求头中,这一切都按预期工作。
我遇到的问题是我如何实际将令牌添加到HttpClient,基本上我是为每个明显错误的请求设置它,否则我会在网上看到其他示例,但我无法确定重构这个的好方法。我读了很多文章,但我发现关于流程这部分的信息很少,所以我猜它可能很简单,以至于指南中从未详细介绍过,但我仍然不知道!
这是调用我的 API 的示例 MVC 操作:
[HttpGet]
[Authorize]
public async Task<IActionResult> GetFromApi()
{
var client = await GetHttpClient();
string testUri = "https://localhost:44308/api/TestItems";
var response = await client.GetAsync(testUri, HttpCompletionOption.ResponseHeadersRead);
var data = await response.Content.ReadAsStringAsync();
GetFromApiViewModel vm = new GetFromApiViewModel()
{
Output = data
};
return View(vm);
}
Run Code Online (Sandbox Code Playgroud)
这是GetHttpClient()我调用的方法(当前驻留在同一个控制器中):
private async Task<HttpClient> GetHttpClient()
{
var client = new HttpClient();
var expat = HttpContext.GetTokenAsync("expires_at").Result;
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 accessToken = await HttpContext.GetTokenAsync("access_token");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
return client;
}
Run Code Online (Sandbox Code Playgroud)
StartUp从我收集的内容来看,我的课程非常标准,但如果它们有用,那么我会将它们添加进去。
我读了很多文章,但我发现关于流程这部分的信息很少,所以我猜它可能很简单,以至于指南中从未详细介绍过,但我仍然不知道!
问题是文档确实散布在各个地方,因此很难全面了解所有最佳实践。我正在计划一个关于“现代 HTTP API 客户端”的博客系列,以收集所有这些最佳实践。
首先,我建议您使用HttpClientFactory而不是新建一个HttpClient.
接下来,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);
}
}
Run Code Online (Sandbox Code Playgroud)
这可以通过 DI 连接:
services.AddTransient<BackendApiAuthenticationHttpClientHandler>();
services.AddHttpClient<MyController>()
.ConfigureHttpClient((provider, c) => c.BaseAddress = new Uri("https://localhost:44308/api"))
.AddHttpMessageHandler<BackendApiAuthenticationHttpClientHandler>();
Run Code Online (Sandbox Code Playgroud)
然后您可以将 anHttpClient注入您的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);
Run Code Online (Sandbox Code Playgroud)
这种模式乍一看似乎很复杂,但它将“我如何调用此 API”逻辑与“此操作在做什么”逻辑分开。并且通过 Polly 使用重试/断路器等更容易扩展。
| 归档时间: |
|
| 查看次数: |
2014 次 |
| 最近记录: |