Blazor InteractiveServer模式下Access Token刷新与HttpClient适配问题
针对你遇到的Token过期后HttpContextAccessor返回旧值、想让HttpClient像Wasm模式那样自动发送Cookie的问题,可以通过以下步骤实现:
1. 配置HttpClient自动携带当前上下文的Cookie
在Program.cs中注册HttpClient时,绑定当前请求的Cookie容器,让HttpClient自动携带认证Cookie,替代手动设置Bearer Token的逻辑:
builder.Services.AddScoped(sp => { var httpContextAccessor = sp.GetRequiredService<IHttpContextAccessor>(); var handler = new HttpClientHandler(); // 将当前HttpContext的Cookie复制到HttpClient的Cookie容器 if (httpContextAccessor.HttpContext?.Request.Cookies.Count > 0) { var apiBaseUri = new Uri("https://your-api-domain.com/"); // 替换为你的API地址 foreach (var cookie in httpContextAccessor.HttpContext.Request.Cookies) { handler.CookieContainer.Add(apiBaseUri, new Cookie(cookie.Key, cookie.Value)); } } return new HttpClient(handler) { BaseAddress = new Uri("https://your-api-domain.com/") }; });
如果API和Blazor服务器同域,可简化apiBaseUri为相对地址,浏览器会自动处理Cookie的域匹配规则。
2. 移除手动设置Bearer Token的代码
删掉所有通过HttpContextAccessor.HttpContext.GetTokenAsync("access_token")获取Token并添加到HttpClient请求头的逻辑,让Cookie自动完成身份验证。
3. 确保API端支持Cookie认证
如果你的API与Blazor服务器共享认证体系,需要在API的Program.cs中配置Cookie认证,使其能通过Cookie识别已认证用户:
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(options => { options.Cookie.Name = ".AspNetCore.Identity.Application"; // 与Blazor服务器使用相同的Cookie名称 options.Events = new CookieAuthenticationEvents { OnValidatePrincipal = context => { // 保留你原有的Token刷新逻辑 return Task.CompletedTask; } }; });
同时在API的中间件管道中启用认证:
app.UseAuthentication(); app.UseAuthorization();
4. 同步刷新后的Cookie到HttpClient
当你通过JS的fetch触发OnValidatePrincipal刷新Cookie后,InteractiveServer模式下的HttpContext不会自动更新(因为Server模式是长连接,初始上下文是页面加载时的状态),需要手动同步最新Cookie到HttpClient:
组件中添加刷新Cookie的方法
@inject IHttpContextAccessor HttpContextAccessor @inject HttpClient HttpClient @code { public async Task RefreshHttpClientCookies() { var httpContext = HttpContextAccessor.HttpContext; if (httpContext == null) return; var handler = HttpClient.HttpMessageHandler as HttpClientHandler; if (handler == null) return; // 重置Cookie容器并添加最新的Cookie handler.CookieContainer = new CookieContainer(); var apiBaseUri = HttpClient.BaseAddress; foreach (var cookie in httpContext.Request.Cookies) { handler.CookieContainer.Add(apiBaseUri, new Cookie(cookie.Key, cookie.Value)); } } }
JS中触发刷新后调用该方法
async function triggerTokenRefresh() { // 调用虚拟API触发Cookie刷新 await fetch('/api/refresh-token'); // 通知Blazor组件同步最新Cookie await DotNet.invokeMethodAsync('YourBlazorAssemblyName', 'RefreshHttpClientCookies'); }
这样配置后,InteractiveServer模式下的HttpClient就会像Wasm模式一样自动携带认证Cookie,无需手动管理JWT Token,同时Cookie刷新后能及时同步到HttpClient,解决Token过期后获取旧值的问题。
内容的提问来源于stack exchange,提问作者ScottexBoy

