asp.net-core - 使用 Blazor Asp.net Core 3.1.0 Preview 3 添加 Jwt HttpClient 处理程序
问题描述
我最近将我的项目从最新版本升级Asp.Net Core 3.0
到了最新版本Asp.Net Core 3.1.0 preview 3
。
JwtTokenHeaderHandler
我的项目正在客户端中运行 Blazor,并且我还截获管道以将 Jwt 添加到使用 my which extends发送回服务器的每个请求的标头中DelegatingHandler
。
我将其添加到startup.cs
我的blazor.client
项目中,如下所示;
services.AddSingleton<HttpClient>(s =>
{
// Creating the URI helper needs to wait until the JS Runtime is initialized, so defer it.
var uriHelper = s.GetRequiredService<NavigationManager>();
var myHandler = s.GetRequiredService<JwtTokenHeaderHandler>();
myHandler.InnerHandler = new WebAssemblyHttpMessageHandler();
return new HttpClient(myHandler)
{
BaseAddress = new Uri(uriHelper.BaseUri)
};
});
但是,自从升级以来似乎WebAssemblyHttpMessageHandler()
不再可用?
我找不到任何有关如何解决此方法的文档。
谁能建议我如何纠正这个问题?
根据 Aqua 的回答进行更新
将以下代码添加到我的Startup.cs
;
services.AddTransient(p =>
{
var wasmHttpMessageHandlerType = Assembly.Load("WebAssembly.Net.Http")
.GetType("WebAssembly.Net.Http.HttpClient.WasmHttpMessageHandler");
var constructor = wasmHttpMessageHandlerType.GetConstructor(Array.Empty<Type>());
return constructor.Invoke(Array.Empty<object>()) as HttpMessageHandler;
})
.AddTransient<JwtTokenHeaderHandler>();
从我的文件中调用Authorized
Get 端点;.razor
var response = await Http.GetAsync<ContactTypeOutputModel[]>("ContactTypes/all");
(上面只是使用扩展方法的类型化包装服务响应);
public static async Task<ServiceResponse<T>> GetAsync<T>(
this HttpClient httpClient, string url)
{
var response = await httpClient.GetAsync(url);
return await BuildResponse<T>(response);
}
我仍然在服务上收到 401?并且没有输出日志表明正在使用该服务?
public class JwtTokenHeaderHandler : DelegatingHandler
{
private readonly IAppLocalStorageService _localStorage;
private readonly ILogger<JwtTokenHeaderHandler> _logger;
private readonly HttpMessageHandler _innerHandler;
private readonly MethodInfo _method;
public JwtTokenHeaderHandler(IAppLocalStorageService localStorage, HttpMessageHandler innerHandler, ILogger<JwtTokenHeaderHandler> logger)
{
_localStorage = localStorage;
_logger = logger;
_innerHandler = innerHandler;
var type = innerHandler.GetType();
_method = type.GetMethod("SendAsync", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod) ?? throw new InvalidOperationException("Cannot get SendAsync method");
WebAssemblyHttpMessageHandlerOptions.DefaultCredentials = FetchCredentialsOption.Include;
}
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
_logger.LogDebug("Adding Jwt to Header from JwtTokenHeaderHandler: SendAsync");
_logger.LogDebug($"Does header contain 'bearer' token: {!request.Headers.Contains("bearer")}");
if (!request.Headers.Contains("bearer"))
{
_logger.LogDebug("Adding Bearer Token to Header");
var savedToken = await _localStorage.GetTokenAsync();
_logger.LogDebug($"Saved Token is : {savedToken}");
if (!string.IsNullOrWhiteSpace(savedToken))
{
request.Headers.Authorization = new AuthenticationHeaderValue("bearer", savedToken);
}
}
//return await base.SendAsync(request, cancellationToken);
return await (_method.Invoke(_innerHandler, new object[] { request, cancellationToken }) as Task<HttpResponseMessage>);
}
}
任何想法为什么这没有被击中?
解决方案
WebAssemblyHttpMessageHandler
已被 Mono 取代,WasmHttpMessageHandler
因为您无法向WebAssembly.Net.Http添加依赖项。为了为 blazor WASM 创建一个 DependencyHandler,我做了一些小技巧:
public class OidcDelegationHandler : DelegatingHandler
{
private readonly IUserStore _userStore;
private readonly HttpMessageHandler _innerHanler;
private readonly MethodInfo _method;
public OidcDelegationHandler(IUserStore userStore, HttpMessageHandler innerHanler)
{
_userStore = userStore ?? throw new ArgumentNullException(nameof(userStore));
_innerHanler = innerHanler ?? throw new ArgumentNullException(nameof(innerHanler));
var type = innerHanler.GetType();
_method = type.GetMethod("SendAsync", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod) ?? throw new InvalidOperationException("Cannot get SendAsync method");
WebAssemblyHttpMessageHandlerOptions.DefaultCredentials = FetchCredentialsOption.Include;
}
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
request.Headers.Authorization = new AuthenticationHeaderValue(_userStore.AuthenticationScheme, _userStore.AccessToken);
return _method.Invoke(_innerHanler, new object[] { request, cancellationToken }) as Task<HttpResponseMessage>;
}
}
是否在 DI 中设置:
return services
.AddTransient(p =>
{
var wasmHttpMessageHandlerType = Assembly.Load("WebAssembly.Net.Http")
.GetType("WebAssembly.Net.Http.HttpClient.WasmHttpMessageHandler");
var constructor = wasmHttpMessageHandlerType.GetConstructor(Array.Empty<Type>());
return constructor.Invoke(Array.Empty<object>()) as HttpMessageHandler;
})
完整代码在这里
推荐阅读
- django - 在 DB django 中插入嵌套关系
- python - 用户详细信息未存储在 Flask Python 中的 SQL alchemy 数据库中
- r - 如何将 R for(){} 函数从 dplyr 重写为 data.table?
- c# - IIS 未压缩 WebAPI JSON 响应
- reactjs - 如何在 scss 文件上加载环境变量
- reactjs - 使用 React Context 从 api 获取数据时获取“null”
- neo4j - neo4j 对时变图建模
- javascript - 有没有办法在 Rails 之外的 Node.JS 中将 Ruby 哈希转换为 JSON?
- javascript - 使用javascript获取浮点数?
- webpack - Webpack 将多个 css 文件组合成一个 CSS 文件