首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Blazor HttpClient Core3.1.0预览3添加Jwt Asp.net Handler

使用Blazor HttpClient Core3.1.0预览3添加Jwt Asp.net Handler
EN

Stack Overflow用户
提问于 2019-11-26 13:11:59
回答 1查看 1.1K关注 0票数 0

最近,我将我的项目从Asp.Net Core 3.0升级到了最新的构建Asp.Net Core 3.1.0 preview 3

我的项目正在客户机中运行Blazor,我还拦截管道,将一个Jwt添加到使用扩展JwtTokenHeaderHandlerDelegatingHandler发送回服务器的每个请求的头上。

我在我的startup.cs blazor.client项目中添加了以下内容:

代码语言:javascript
复制
        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之后;

代码语言:javascript
复制
        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文件中调用一个.razor获取端点;

代码语言:javascript
复制
var response = await Http.GetAsync<ContactTypeOutputModel[]>("ContactTypes/all");

(上面只是使用扩展方法的类型包装服务响应);

代码语言:javascript
复制
    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的服务吗?而没有输出日志来表示服务正在被使用?

代码语言:javascript
复制
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>);
    }
}

知道为什么这个没被击中吗?

EN

回答 1

Stack Overflow用户

发布于 2019-11-26 13:37:58

由于无法向WebAssembly.Net.Http.添加依赖项,WebAssemblyHttpMessageHandler已被Mono的WasmHttpMessageHandler替换为了为blazor创建一个DependencyHandler,我做了一个小黑客:

代码语言:javascript
复制
    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中将其设置为:

代码语言:javascript
复制
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;
    })

完整的代码是这里

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59051760

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档