如何为Blazor WASM自动生成的OpenAPI代码添加认证令牌
解决方案:给Blazor WASM自动生成的OpenAPI客户端添加JWT认证头
要实现每次请求自动注入JWT令牌,同时配合自动生成的CustomApi客户端,你可以通过自定义DelegatingHandler拦截请求的方式实现,既不用修改自动生成的代码,也能动态获取最新令牌。
步骤1:创建自定义认证请求拦截器
这个Handler会在每次请求发送前,从AuthenticationStateProvider(或直接从LocalStorage)获取令牌并添加到请求头:
using System.Net.Http; using System.Net.Http.Headers; using System.Security.Claims; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Components.Authorization; public class AuthHeaderHandler : DelegatingHandler { private readonly AuthenticationStateProvider _authStateProvider; public AuthHeaderHandler(AuthenticationStateProvider authStateProvider) { _authStateProvider = authStateProvider; } protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { // 获取当前认证状态 var authState = await _authStateProvider.GetAuthenticationStateAsync(); var user = authState.User; // 如果用户已认证,添加Bearer令牌 if (user.Identity is { IsAuthenticated: true }) { // 这里的Claim名称要和你存储JWT时的字段匹配,比如"access_token"或"jwt" var token = user.FindFirst("access_token")?.Value; if (!string.IsNullOrEmpty(token)) { request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token); } } // 继续发送请求 return await base.SendAsync(request, cancellationToken); } }
如果你的令牌是直接存在LocalStorage而非通过AuthenticationStateProvider暴露的,可以改用Blazored.LocalStorage直接读取:
using Blazored.LocalStorage; // ... public class AuthHeaderHandler : DelegatingHandler { private readonly ILocalStorageService _localStorage; public AuthHeaderHandler(ILocalStorageService localStorage) { _localStorage = localStorage; } protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { var token = await _localStorage.GetItemAsStringAsync("jwt_token"); // 替换为你的LocalStorage键名 if (!string.IsNullOrEmpty(token)) { request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token); } return await base.SendAsync(request, cancellationToken); } }
步骤2:在Program.cs中注册服务
修改Program.cs的服务注册逻辑,将自定义Handler、HttpClient和自动生成的CustomApi关联起来:
var builder = WebAssemblyHostBuilder.CreateDefault(args); builder.RootComponents.Add<App>("#app"); // 1. 注册自定义认证Handler(Scoped生命周期,确保每次请求能获取最新令牌) builder.Services.AddScoped<AuthHeaderHandler>(); // 2. 注册带认证拦截的HttpClient builder.Services.AddScoped(sp => { var authHandler = sp.GetRequiredService<AuthHeaderHandler>(); var httpClient = new HttpClient(authHandler) { BaseAddress = new Uri(builder.Configuration["BaseUrl"]) }; return httpClient; }); // 3. 注册自动生成的CustomApi,注入配置好的HttpClient builder.Services.AddScoped<CustomApi>(sp => { var httpClient = sp.GetRequiredService<HttpClient>(); // 根据自动生成的构造函数调整:如果构造函数是(string baseUrl, HttpClient client),则传入BaseUrl return new CustomApi(builder.Configuration["BaseUrl"], httpClient); // 如果构造函数只接受HttpClient,直接传:return new CustomApi(httpClient); }); // 如果用Blazored.LocalStorage,需要先注册 // builder.Services.AddBlazoredLocalStorage(); // 注册你的自定义AuthenticationStateProvider builder.Services.AddScoped<AuthenticationStateProvider, CustomAuthenticationStateProvider>(); builder.Services.AddAuthorizationCore(); await builder.Build().RunAsync();
关键说明
- 为什么用DelegatingHandler?
自动生成的OpenAPI客户端会直接使用注入的HttpClient,通过Handler拦截请求,无需修改生成的代码,就能统一处理所有请求的认证头。 - Scoped生命周期的作用
Blazor WASM中Scoped服务对应每个浏览器标签页实例,每次请求都会通过Handler获取最新的认证状态,避免使用过期令牌。 - 避免在Program.cs直接访问LocalStorage
Program.cs是应用启动阶段执行的代码,此时还未进入浏览器环境,无法直接调用LocalStorage API,必须通过Scoped服务(如Handler)在运行时动态获取。
内容的提问来源于stack exchange,提问作者seho
相关产品推荐
相关产品推荐

