Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/apache/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在Blazor wasm中将访问令牌自动附加到HTTP客户端_C#_Asp.net Core_Blazor_Blazor Client Side_Blazor Webassembly - Fatal编程技术网

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

C# 在Blazor wasm中将访问令牌自动附加到HTTP客户端,c#,asp.net-core,blazor,blazor-client-side,blazor-webassembly,C#,Asp.net Core,Blazor,Blazor Client Side,Blazor Webassembly,我正在为我的Blazor wasm应用程序使用一个开放id连接身份提供程序,并希望将一个访问令牌连接到http客户端,如本文所述 但是,每当我创建http客户机并尝试使用它时,即使登录,也会收到AccessTokenNotAvailableException 以下是我所拥有的: 在Program.cs中 //为CustomAuthorizationMessageHandler添加服务 builder.Services.addScope(); //用于向API请求的Http客户端 builder.

我正在为我的Blazor wasm应用程序使用一个开放id连接身份提供程序,并希望将一个访问令牌连接到http客户端,如本文所述

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

以下是我所拥有的:

在Program.cs中

//为CustomAuthorizationMessageHandler添加服务
builder.Services.addScope();
//用于向API请求的Http客户端
builder.Services.AddHttpClient(“API”,客户端=>
{
//将基址设置为API url
client.BaseAddress=新Uri(“https://localhost:44370");
//将请求头设置为application/json
client.DefaultRequestHeaders.Accept.Add(新的System.Net.Http.Headers.MediaTypeWithQualityHeaderValue(“应用程序/json”);
}).AddHttpMessageHandler();
//Auth0身份验证设置
builder.Services.AddOidcAuthentication(选项=>
{
builder.Configuration.Bind(“Auth0”,options.ProviderOptions);
options.ProviderOptions.ResponseType=“代码”;
});
CustomAuthorizationHandler.cs

公共类CustomAuthorizationMessageHandler:AuthorizationMessageHandler { 公共CustomAuthorizationMessageHandler(IAccessTokenProvider提供程序, 导航管理器(导航管理器) :base(提供程序、navigationManager) { 配置处理程序( authorizedUrls:新[]{”https://localhost:44370" }, 作用域:新[]{“admin”}); } } 尝试访问api时

试试看
{
var client=ClientFactory.CreateClient(“API”);
message=wait client.GetStringAsync(“api/message”);
}
捕获(AccessTokenNotAvailableException e)
{
message=“您无法访问api,请登录”;
}
目前,在Program.cs中删除AddHttpMessageHandler调用时,下面的代码可以从api获取消息,但我不希望每次进行api调用时都必须获取访问令牌。TokenProvider的类型为IAccessTokenProvider,并被注入

var client=ClientFactory.CreateClient(“API”);
使用(var requestMessage=newhttprequestmessage(HttpMethod.Get,“api/message”))
{
var tokenResult=wait TokenProvider.RequestAccessToken();
if(tokenResult.TryGetToken(out-var-token))
{
requestMessage.Headers.Authorization=新的AuthenticationHeaderValue(“承载者”,token.Value);
var response=await client.sendsync(requestMessage);
if(响应。IsSuccessStatusCode)
{
message=wait response.Content.ReadFromJsonAsync();
}
其他的
{
message=wait response.Content.ReadAsStringAsync();
}
}
其他的
{
message=“您无法访问api,请登录”;
}
}

如何解决此问题,使我不会每次都收到AccessTokenNotAvailableException?

已经明确指出,需要为传出请求配置消息处理程序,建议实现自定义消息处理程序。 再次………为了配置消息处理程序,您实现了一个自定义消息处理程序。这是定制的唯一目的。当然,您可以重写SendAsync方法,如果有这样的操作,您知道自己在做什么,并且您可以适当地这样做。但这并不是一种引入bug并使SendAsync无效的方法

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

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

以上解决了您遇到的问题…也就是说,配置scopes属性(
scopes:new[]{“admin”})),可以省略

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

builder.Services.AddTransient(sp => sp.GetRequiredService<IHttpClientFactory> 
   ().CreateClient("ServerAPI"));
注意:为了使用GetFromJsonAsync方法,您应该安装 System.Net.Http.Json包

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

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

builder.Services.addScope();
builder.Services.AddHttpClient(“ServerAPI”,client=>client.BaseAddress=新Uri(builder.hostenEnvironment.BaseAddress))
.AddHttpMessageHandler();
builder.Services.AddTransient(sp=>
sp.GetRequiredService().CreateClient(“ServerAPI”);

您使用的是什么身份提供者?IdentityServer4还是其他什么?@CobyC我们正在使用Auth0Ok,您添加了一个指向该站点的链接,但也有一篇文章解释了Auth0的实现。我只完成了IdentityServer4实现。我看不到
AddOidcAuthentication()
在Auth0文章中提到的
程序.cs
设置中。@CobyC我编辑了我的文章,以在程序中显示我的Auth0 oicd实现。cs@CobyC我使用那篇Auth0文章来设置Authentication。结果发现ConfigureHandler方法中的scopes参数给我带来了麻烦,所以我删除了它,它就工作了。我没有想到重写sendaync方法,但我认为这也可以。谢谢你的帮助!很高兴你成功了!授权和身份验证是一个相当复杂的主题,有时文档对其解释不够充分。我将注释范围行以供进一步参考。@CobyC,除非您是接受答案的用户,否则您不能删除接受的答案。然而,由于我通常会删除我的答案,如果他们不被接受,我会将我的答案移至你的帖子并删除我的。
builder.Services.AddTransient(sp => sp.GetRequiredService<IHttpClientFactory> 
   ().CreateClient("ServerAPI"));
protected override async Task OnInitializedAsync()
    {
        try
        {
           message= await Http.GetFromJsonAsync<string>("api/message");
        }
        catch (AccessTokenNotAvailableException exception)
        {
            exception.Redirect();
        }
    } 
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"));