如何使用 blazor 前端 http 请求附加令牌

Jos*_*ing 2 api asp.net-core blazor

我使用 blazor 作为前端,api 已完成 JWT 配置。前端可以创建用户帐户并登录API,但现在我的前端httpclient没有设置JWT令牌,所以如果我在Api控制器中设置[授权],前端将无法访问它。

api程序代码如下

builder.Services.AddIdentity<IdentityUser, IdentityRole>().AddEntityFrameworkStores<DBContext>();//add user model,role model and connect toDbcontext
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options => {
        options.TokenValidationParameters = new TokenValidationParameters() {
            ValidateIssuer = true,
            ValidIssuer = builder.Configuration["Authentication:Issuer"],
            ValidateAudience = true,
            ValidAudience = builder.Configuration["Authentication:Audience"],
            ValidateLifetime = true,
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Authentication:SecretKey"]))
        };
    }); 
Run Code Online (Sandbox Code Playgroud)

控制器代码如下

   [HttpGet("all")]
    [HttpHead]
    //[Authorize(AuthenticationSchemes = "Bearer")]
    [Authorize]
    public async Task<ActionResult<IEnumerable<Quiz>>> GetQuizzesDetailsAsync() {
     
       var quizzes= await _quizzesRepository.GetQuizzesDetailsAsync( );
        var quizDtos=_mapper.Map<IEnumerable<QuizOverviewDto>>(quizzes);
        return Ok(quizDtos);
    }
Run Code Online (Sandbox Code Playgroud)

前端 Blazor 程序代码如下

builder.Services.AddHttpClient<IQuizService, QuizService>(
      client => client.BaseAddress = new Uri("https://localhost:7172"))
    .AddHttpMessageHandler<CustomAuthorizationMessageHandler>();
Run Code Online (Sandbox Code Playgroud)

和“CustomAuthorizationMessageHandler”代码如下。

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

    }
}
Run Code Online (Sandbox Code Playgroud)

}

访问服务如下

        public async Task<IEnumerable<QuizOverviewDto>> GetQuizzesDetailsAsync() {         
            return await JsonSerializer.DeserializeAsync<IEnumerable<QuizOverviewDto>>(
await _httpClient.GetStreamAsync("api/quizzes/all"),
new JsonSerializerOptions {
    PropertyNameCaseInsensitive = true
});
        } 
Run Code Online (Sandbox Code Playgroud)

现在当我调用 GetQuizzesDetailsAsync() 这个服务时,它给我一个错误。

Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100] 未处理的异常呈现组件:尝试激活“PerfectPoliciesFE.CustomAuthorizationMessageHandler”时无法解析类型“Microsoft.AspNetCore.Components.WebAssembly.Authentication.IAccessTokenProvider”的服务。System.InvalidOperationException:尝试激活“PerfectPoliciesFE.CustomAuthorizationMessageHandler”时无法解析类型“Microsoft.AspNetCore.Components.WebAssembly.Authentication.IAccessTokenProvider”的服务。在 Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(类型实现类型,CallSiteChain callSiteChain,ParameterInfo []参数,布尔型 throwIfCallSiteNotFound) 在 Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache 生命周期,类型 serviceType,类型实现类型,CallSiteChain调用站点链)

我的代码有什么问题?我想我只将登录用户的令牌附加到http请求,并且它可以成功访问,有什么简单的方法可以做到这一点吗?

Raf*_*ffy 5

如果您使用 Blazor WebAssembly,则需要IAccessTokenProviderMicrosoft.AspNetCore.Components.WebAssembly.Authentication服务内的命名空间注入 并从那里获取令牌。获得令牌后,您可以将令牌值传递到 httpclient 的 Authorization 标头。

private readonly IAccessTokenProvider _tokenProvider;
private readonly HttpClient _httpClient;

public class QuizService(IAccessTokenProvider tokenProvider, HttpClient httpClient)
{
    _tokenProvider = tokenProvider;
    _httpClient = httpClient;
}

private async Task RequestAuthToken()
{
    var requestToken = await _tokenProvider.RequestAccessToken();
    requestToken.TryGetToken(out var token);
    _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token.Value);
}

public async Task<IEnumerable<QuizOverviewDto>> GetQuizzesDetailsAsync() 
{  
  await RequestAuthToken();
  return await JsonSerializer.DeserializeAsync<IEnumerable<QuizOverviewDto>>(
    await _httpClient.GetStreamAsync("api/quizzes/all"),
    new JsonSerializerOptions {
        PropertyNameCaseInsensitive = true
    });
 } 
Run Code Online (Sandbox Code Playgroud)