在 Blazor wasm 中自动将访问令牌附加到 HTTP 客户端

2023-12-26

我正在为我的 Blazor wasm 应用程序使用开放 id 连接身份提供程序,并且希望将访问令牌附加到 http 客户端,如中所述this https://learn.microsoft.com/en-us/aspnet/core/blazor/security/webassembly/additional-scenarios?view=aspnetcore-3.1#attach-tokens-to-outgoing-requests文章。

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

这是我所拥有的:

在程序.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";
});

自定义AuthorizationHandler.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 类型并被注入。

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?


已经明确指出有two ways https://learn.microsoft.com/en-us/aspnet/core/blazor/security/webassembly/additional-scenarios?view=aspnetcore-3.1#attach-tokens-to-outgoing-requests要为传出请求配置消息处理程序,建议实现自定义消息处理程序。 再次......您实现一个自定义消息处理程序以配置消息处理程序。这就是定制的唯一目的。当然,您可以重写 SendAsync 方法,如果这样的操作到位,您就知道自己在做什么,并且可以适当地执行该操作。但并不是引入错误并实际上使 SendAsync 无效的一种方式。

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

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: new[] { "admin" });),可以省略。

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

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

并将其注入到您的组件中,如下所示:@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包

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

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

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"));
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Blazor wasm 中自动将访问令牌附加到 HTTP 客户端 的相关文章

随机推荐

  • 如何使用 beforeUpdate Hook Sequelize 中止更新操作

    我如何使用sequelize上的beforeUpdate钩子中止更新操作并返回一个对象作为中止更新的结果 如果我有类似的东西 User beforeUpdate function user options if user name exam
  • TWTRTwitter sessionStore 现在返回 TWTRAuthSession:那么现在如何访问 userName 属性呢?

    使用 Swift 中的 TwitterKit 3 3 0sharedInstance sessionStore session 现在返回一个TWTRAuthSession而不是一个TWTRSession 像之前一样 事情发生了变化 但这很好
  • PerformBlockAndWait 造成死锁

    我正在编写一个执行一些 CoreData 操作的函数 我希望该函数仅返回after所有 CoreData 操作均已执行 CoreData 的内容涉及在后台上下文中创建一个对象 然后在父上下文中执行更多操作 void myFunction N
  • 声明和未声明变量的影响

    JavaScript 声明变量和未声明变量之间的主要区别是什么 删除运算符对声明的变量不起作用 var y 43 declares a new variable x 42 delete x returns true x is a prope
  • 我是否正确消毒/逃生?

    我用 PHP 编写了一个简单的搜索脚本 用于搜索 mySQL 数据库并输出结果 它的工作原理是这样的 用户通过搜索表单搜索 jack s 我的 PHP 脚本GET就是这个搜索 并对其进行清理 然后是脚本 使用SELECT and LIKE
  • 检查 C++ 中多个值的相等性

    我正在 C 中寻找一种简单 快速且描述性的方法来检查某个值是否包含在一组固定的其他值中 就像在 Python 中一样 人们可以在其中编写 if some function in 2 3 5 7 11 do something 一些明显的选择
  • Java 自动装箱和三元运算符的疯狂

    刚刚花了几个小时调试这段代码 令人沮丧 LinkedHashMap
  • 使用 monad 读取 INI 文件

    我正在尝试使用 monads 使用 haskell 读取 INI 文件 这是我的代码 import Control Monad import Data Ini main do config lt readIniFile configs co
  • 是否可以在拉取请求(Github)中更改其他人的代码?

    在 Github 项目上 我看到有人在Pull Requests部分 但我发现他犯了很多错误 因此他的代码需要更正 与其要求他改他的代码 是不是可以自己动手 就是我想自己改他的代码 如何 我也是该项目的成员 而且我是新人 对现有拉取请求启用
  • Fabric 网络 - 当宕机的对等点连接回网络时会发生什么?

    我最近使用 Docker compose 部署了结构网络 我试图模拟一个宕机的对等点 本质上是这样的 使用运行结构网络的 docker compose 将 4 个对等点联机 1 个对等点 即第 4 个对等点出现故障 通过 docker st
  • Liferay 搜索容器分页

    我在代码中使用了 liferay ui search container 搜索结果会正确显示 直到我单击 下一步 该 portlet 正在重新加载 这会将我带到该 portlet 的第一页 从而破坏了所显示的搜索结果 即使在 portlet
  • Laravel 5.8 - 如何将文件从存储目录移动到公共目录?

    我想将我的一个文件从storageLaravel 中的文件目录publiclaravel 中的文件目录 无需更改我的文件系统配置 这可能吗 是的 你可以这样做存储 移动 https laravel com docs 5 8 filesyst
  • 网格中两点之间的最短路径。有一个捕获

    我遇到这个问题 我必须通过向右或向下移动来找到 NxM 网格中从 A 点 总是左上角 到 B 点 总是右下角 的最短路径 听起来很容易 是吗 问题是 我只能移动我现在坐在的图块上显示的数字 让我举例说明 2 5 1 2 9 2 5 3 3
  • 防止 jquery mobile 设置元素样式

    我想在页面上隐藏一个复选框 我明显的第一次尝试如下
  • 来自 EventEmitter 的热共享 Observable

    有没有办法从一个EventEmitter 或 Angular 2 alpha 46 RxJS 5 alpha 中可用的等效项 IE 如果我们在值解析后订阅 它将使用之前解析的值触发 类似于我们总是返回相同的承诺 理想情况下 仅使用 Angu
  • 在 PHP 中实现切削库存算法

    我需要实施下料问题 http en wikipedia org wiki Cutting stock problem与 php 脚本 由于我的数学能力不是很好 所以我只是想用暴力来解决 从这些参数开始 inventory 是可剪切的长度数组
  • 使用斯坦福 CoreNLP 解决共指问题 - 无法加载解析器模型

    我想做一项非常简单的工作 给定一个包含代词的字符串 我想解析它们 例如 我想把这句话 Mary has a Littlelamb She is Cute 在 玛丽有一只小羊羔 玛丽很可爱 中 我尝试过使用斯坦福 CoreNLP 但是 我似乎
  • 如何使用 jQuery 检测 URL 更改

    jQuery 如何检测 url 的更改 例如 如果用户转到某个页面site com faq 没有任何显示 但如果他去site com faq openjquery 检测到它并执行某些操作 尝试这个 window on hashchange
  • 为什么 dplyr 的 top_n() 不起作用?

    我有一个名为的数据框df City State Price Dogs Portland OR 75 1 Portland OR 100 3 San Diego CA 12 4 San Diego CA 23 5 I used dplyr s
  • 在 Blazor wasm 中自动将访问令牌附加到 HTTP 客户端

    我正在为我的 Blazor wasm 应用程序使用开放 id 连接身份提供程序 并且希望将访问令牌附加到 http 客户端 如中所述this https learn microsoft com en us aspnet core blazo