在Blazor wasm中将访问令牌自动附加到HTTP客户端 [英] Automatically Attaching Access Token to HTTP Client in Blazor wasm

查看:93
本文介绍了在Blazor wasm中将访问令牌自动附加到HTTP客户端的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为我的Blazor wasm应用程序使用开放ID连接身份提供程序,并希望将访问令牌附加到http客户端,如

I am using an open id connect identity provider for my Blazor wasm application and would like an access token to be attached to the http client as described in this article.

但是,每当我创建http客户端并尝试使用它时,即使登录,我也会收到AccessTokenNotAvailableException.

However, whenever I create the http client and try to use it I am getting an AccessTokenNotAvailableException, even when logged in.

这就是我所拥有的:

在Program.cs

In Program.cs

// Add service for CustomAuthorizationMessageHandler
builder.Services.AddScoped<CustomAuthorizationMessageHandler>();

// Http client for requests to API
builder.Services.AddHttpClient("API", client =>
{
    // Set base address to API url
    client.BaseAddress = new Uri("https://localhost:44370");

    // Set request headers to application/json
    client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
}).AddHttpMessageHandler<CustomAuthorizationMessageHandler>();

// Auth0 authentication setup
builder.Services.AddOidcAuthentication(options =>
{
    builder.Configuration.Bind("Auth0", options.ProviderOptions);
    options.ProviderOptions.ResponseType = "code";
});

CustomAuthorizationHandler.cs

CustomAuthorizationHandler.cs

public class CustomAuthorizationMessageHandler : AuthorizationMessageHandler
{
    public CustomAuthorizationMessageHandler(IAccessTokenProvider provider,
        NavigationManager navigationManager)
        : base(provider, navigationManager)
    {
        ConfigureHandler(
            authorizedUrls: new[] { "https://localhost:44370" },
            scopes: new[] { "admin" });
    }
}

尝试访问api时

try
{
    var client = ClientFactory.CreateClient("API");
    message = await client.GetStringAsync("api/message");
}
catch (AccessTokenNotAvailableException e)
{
    message = "You CANNOT access the api. Please log in";
}

当前,当删除Program.cs中的AddHttpMessageHandler调用时,以下代码可从api获取消息,但我不想每次进行api调用时都必须获取访问令牌.TokenProvider的类型为IAccessTokenProvider,并已插入.

Currently, the below code works to get the message from the api when removing the AddHttpMessageHandler call in Program.cs but I don't want to have to get the access token every time I make an api call. TokenProvider is of type IAccessTokenProvider and is injected in.

var client = ClientFactory.CreateClient("API");
using (var requestMessage = new HttpRequestMessage(HttpMethod.Get, "api/message"))
{
    var tokenResult = await TokenProvider.RequestAccessToken();

    if (tokenResult.TryGetToken(out var token))
    {
        requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token.Value);
        var response = await client.SendAsync(requestMessage);
        if(response.IsSuccessStatusCode)
        {
            message = await response.Content.ReadFromJsonAsync<string>();
        }
        else
        {
            message = await response.Content.ReadAsStringAsync();
        }
    }
    else
    {
        message = "You CANNOT access the api. Please log in";
    }
}

如何解决此问题,以免每次都不会出现AccessTokenNotAvailableException?

How can I fix this so I don't get an AccessTokenNotAvailableException every time?

推荐答案

显然已声明存在

It has clearly been stated that there are two ways to configure a message handler for outgoing requests, recommending implementing a custom message handler. Once again.........you implement a custom message handler in order to CONFIGURE the message handler. That's the sole purpose of the customization. Of course, you may override the SendAsync method, if such an action is in place, you know what you do, and you do that appropriately. But not as a way to introduce bugs and actually make the SendAsync invalid.

这是自定义消息处理程序的实现:

Here's the implementation of the custom message handler:

using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;

-

public class CustomAuthorizationMessageHandler : AuthorizationMessageHandler
    {
        public CustomAuthorizationMessageHandler(IAccessTokenProvider provider,
            NavigationManager navigationManager)
            : base(provider, navigationManager)
        {
            ConfigureHandler(
               authorizedUrls: new[] { "https://localhost:44370" });
    
        }
    }   

以上内容解决了您遇到的问题...也就是说,配置scopes属性( scopes:new [] {"admin"}); ),可以将其忽略

The above solve the issue you had...that is to say, configuring the scopes property (scopes: new[] { "admin" });), which can be left out.

以下是一些改进代码的建议:创建一个名为HttpClient的服务,如下所示.

The following are some suggestions to improve your code: Create a named HttpClient service as follows.

builder.Services.AddTransient(sp => sp.GetRequiredService<IHttpClientFactory> 
   ().CreateClient("ServerAPI"));

并将其注入到您的组件中,如下所示: @inject HttpClient Http

And inject it into your component like this: @inject HttpClient Http

并像这样使用它:

protected override async Task OnInitializedAsync()
    {
        try
        {
           message= await Http.GetFromJsonAsync<string>("api/message");
        }
        catch (AccessTokenNotAvailableException exception)
        {
            exception.Redirect();
        }
    } 

注意:为了使用GetFromJsonAsync方法,您应该安装System.Net.Http.Json包

Note: In order to use the GetFromJsonAsync method, you should install the System.Net.Http.Json package

请注意,以上是处理Http请求的正确方法.这包括将用户重定向到登录页面.当然,您可以生成任何要显示给用户的消息,但是重定向是正确的方法.

Note that the above is the proper way to handle the Http request. That includes redirecting the user to a login page. Of course you may produce whatever message you want to display to your user, but the redirection is the proper way.

应用上述建议的更改后,您的Program.Main方法应具有以下设置(请注意顺序):

After applying the suggested changes above, your Program.Main method should have the following settings (pay attention to order):

builder.Services.AddScoped<CustomAuthorizationMessageHandler>();

            builder.Services.AddHttpClient("ServerAPI", client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress))
               .AddHttpMessageHandler<CustomAuthorizationMessageHandler>();
                
            builder.Services.AddTransient(sp => 
   sp.GetRequiredService<IHttpClientFactory>().CreateClient("ServerAPI"));

这篇关于在Blazor wasm中将访问令牌自动附加到HTTP客户端的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆