c# - ASP.NET Core Web API - JWT 消息处理程序 - 无注册类型错误
问题描述
我为我的 Web API 项目创建了一个 JWT 令牌处理程序。这个想法是,这个 API 只是一个通往其他 API 的网关,并且一个令牌在它们之间共享。因此,当调用我的 API 并将调用转发给另一个时,我想自动转发附加到初始请求的 JWT。
我制作了一个自定义 MessageHandler ,如下所示:
public class JwtTokenHeaderHandler : DelegatingHandler
{
private readonly HttpContext httpContext;
public JwtTokenHeaderHandler(HttpContext httpContext)
{
this.httpContext = httpContext;
}
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
string savedToken = await this.httpContext.GetTokenAsync("access_token");
request.Headers.Add("bearer", savedToken);
return await base.SendAsync(request, cancellationToken);
}
}
然后我在 Startup 中将其注册为服务,如下所示:
services.AddTransient<HttpMessageHandler>(p => p.GetRequiredService<JwtTokenHeaderHandler>());
IHttpClientBuilder serviceClientBuilder = services.AddHttpClient<IService, Service>(client =>
{
client.BaseAddress = new Uri(this.Configuration.GetValue<string>("ServiceURL"));
}).AddHttpMessageHandler<JwtTokenHeaderHandler>();
应用程序一直运行,直到发出请求,然后出现此异常:
执行请求时发生未处理的异常。
System.InvalidOperationException:未注册“Application.API1.JwtTokenHeaderHandler”类型的服务。在 Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType) 在 Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider) 在 Microsoft.Extensions.DependencyInjection.HttpClientBuilderExtensions.<>c__4`1.b__4_1 (HttpMessageHandlerBuilder b) 在 Microsoft.Extensions.Http.DefaultHttpClientFactory.<>c__DisplayClass17_0.g__Configure|0(HttpMessageHandlerBuilder b) 在 Microsoft.Extensions.Http.LoggingHttpMessageHandlerBuilderFilter.<>c__DisplayClass3_0.b__0(HttpMessageHandlerBuilder builder)
解决方案
首先,直接注入HttpContext
会导致问题。IHttpContextAccessor
在 Send 方法中使用和访问上下文。
public class JwtTokenHeaderHandler : DelegatingHandler {
private readonly IHttpContextAccessor accessor;
public JwtTokenHeaderHandler(IHttpContextAccessor accessor) {
this.accessor = accessor;
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) {
string savedToken = await accessor.HttpContext.GetTokenAsync("access_token");
request.Headers.Add("bearer", savedToken);
return await base.SendAsync(request, cancellationToken);
}
}
当请求的服务未在集合中注册时, NextGetRequiredService
会引发该异常,因此请确保将处理程序注册到容器中
笔记
处理程序类型必须注册为临时服务。
参考AddHttpMessageHandler<THandler>(IHttpClientBuilder)
services.AddTransient<JwtTokenHeaderHandler>();
这样JwtTokenHeaderHandler
就可以在服务提供商提出要求时解决
services.AddTransient<HttpMessageHandler>(p => p.GetRequiredService<JwtTokenHeaderHandler>());
services.AddHttpClient<IService, Service>(client => {
client.BaseAddress = new Uri(this.Configuration.GetValue<string>("ServiceURL"));
}).AddHttpMessageHandler<JwtTokenHeaderHandler>();
推荐阅读
- amazon-web-services - AWS Elastic Beanstalk 不可变更新选项不可用
- php - 如何让 PHP 调试器在 VsCode 中的 docker 容器内的断点处中断?
- reactjs - 使用 react-google-maps 获取绘制的多边形或任何形状下覆盖的所有标记的详细信息
- boto3 - boto3 send_bonus 操作因 ParameterValidationError 而失败
- jsf - 汇总行 JSF 数据表
- javascript - 如果值数组存在于 ES6、Javascript 中的另一个对象数组中,则删除或推送
- sql - 请提供简单的 SQL Server 语法帮助
- php - Laravel:输出值作为星级
- reactjs - 重新加载页面时 Firebase 身份验证返回 false
- pine-script - 距离栏关闭的剩余秒数 - 松树脚本