【问题标题】:Adding Jwt HttpClient Handler with Blazor Asp.net Core 3.1.0 Preview 3使用 Blazor Asp.net Core 3.1.0 Preview 3 添加 Jwt HttpClient 处理程序
【发布时间】:2019-11-27 00:31:44
【问题描述】:

我最近将我的项目从 Asp.Net Core 3.0 升级到最新版本 Asp.Net Core 3.1.0 preview 3

我的项目正在客户端中运行 Blazor,并且我还截获了管道,以使用扩展 DelegatingHandlerJwtTokenHeaderHandler 将 Jwt 添加到发送回服务器的每个请求的标头中。

我在我的blazor.client 项目的startup.cs 中添加如下;

        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 从我的.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>);
    }
}

任何想法为什么没有被击中?

【问题讨论】:

    标签: asp.net-core blazor blazor-client-side


    【解决方案1】:

    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;
        })
    
    

    完整代码是here

    【讨论】:

    • 非常感谢,但它似乎仍然没有影响到我的JwtTokenHeaderHandler,所以我的请求被 401 拒绝了。我会用我的步骤更新问题。
    • 好的,我已更新问题以包含所有更新代码。感谢您为此提供的所有帮助。
    • 嗯,您使用的 HttpClient 实例似乎不是您在 DI 中设置的实例。您是否尝试使用 `new HttpClient(JwtTokenHeaderHandler)' 创建客户端?
    • 不,目前我只是在我的 ..razor 中使用开箱即用的 HttpClient,即 @inject HttpClient Http。对于以前的版本,它只会拦截管道。我还在Startup.cs 中添加了services.AddHttpClient()? (基于您的回购链接)
    • 您是指从.razor 级别还是在Startup.cs 中设置DI 时?
    猜你喜欢
    • 2020-07-25
    • 2023-03-12
    • 2018-06-06
    • 1970-01-01
    • 2023-02-10
    • 2020-05-30
    • 2020-08-05
    • 1970-01-01
    • 2012-04-15
    相关资源
    最近更新 更多