.NET 8 Preview 7新版Blazor模板中AuthenticationState无法正常工作
解决.NET 8 Preview 7混合Blazor模板认证预渲染错误
错误原因
该错误源于预渲染阶段(服务器端静态生成HTML时)没有JavaScript运行时环境,但RemoteAuthenticationService在初始化AuthenticationStateProvider时调用了JavaScript互操作(比如读取浏览器存储的认证令牌),违反了预渲染阶段不能执行JS互操作的限制。旧项目的解决方案失效,是因为.NET 8混合模板采用了新的交互式渲染模式配置逻辑,原有的_Host.cshtml路径判断方式不再适配新的路由体系。
解决方案
方案一:针对认证路径禁用预渲染
在Server项目的Program.cs中,为/authentication路径单独配置渲染规则,强制使用非预渲染的WebAssembly模式:
var builder = WebApplication.CreateBuilder(args); // 常规混合模式路由配置 builder.Services.AddRazorComponents() .AddInteractiveServerRenderMode() .AddInteractiveWebAssemblyRenderMode() .AddAdditionalAssemblies(typeof(Client._Imports).Assembly); var app = builder.Build(); // 其他中间件配置(静态文件、路由等) app.UseStaticFiles(); app.UseAntiforgery(); // 为认证路径单独设置渲染模式,禁用预渲染 app.MapWhen(ctx => ctx.Request.Path.StartsWithSegments("/authentication"), subApp => { subApp.MapRazorComponents<Client.App>() .AddInteractiveWebAssemblyRenderMode(prerender: false); }); // 其他路径使用默认混合模式 app.MapRazorComponents<Client.App>() .AddInteractiveServerRenderMode() .AddInteractiveWebAssemblyRenderMode() .AddAdditionalAssemblies(typeof(Client._Imports).Assembly); app.Run();
方案二:在认证组件上直接指定渲染模式
在登录、注册等认证相关组件(如Authentication.razor)顶部添加@rendermode指令,强制该组件使用非预渲染的WebAssembly模式:
@rendermode RenderMode.InteractiveWebAssembly(prerender: false) <!-- 组件内容 -->
方案三:自定义认证状态提供器规避预渲染JS调用
创建一个包装原有认证服务的自定义AuthenticationStateProvider,预渲染时返回匿名状态,待客户端渲染完成后再获取真实认证状态:
- 定义自定义提供器:
using Microsoft.AspNetCore.Components.WebAssembly.Authentication; using System.Security.Claims; public class PrerenderSafeAuthStateProvider : AuthenticationStateProvider { private readonly RemoteAuthenticationService<RemoteAuthenticationState, RemoteUserAccount, OidcProviderOptions> _innerAuthService; private bool _isPrerendering = true; public PrerenderSafeAuthStateProvider(RemoteAuthenticationService<RemoteAuthenticationState, RemoteUserAccount, OidcProviderOptions> innerAuthService) { _innerAuthService = innerAuthService; } public void MarkAsPostPrerender() { _isPrerendering = false; NotifyAuthenticationStateChanged(GetAuthenticationStateAsync()); } public override async Task<AuthenticationState> GetAuthenticationStateAsync() { if (_isPrerendering) { // 预渲染时返回匿名身份 return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity())); } return await _innerAuthService.GetAuthenticationStateAsync(); } }
- 在Server项目
Program.cs中注册该提供器:
builder.Services.AddScoped<AuthenticationStateProvider, PrerenderSafeAuthStateProvider>();
- 在
App.razor中触发状态更新:
@inject PrerenderSafeAuthStateProvider AuthStateProvider <Router AppAssembly="@typeof(App).Assembly"> <!-- 路由内容 --> </Router> @code { protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { AuthStateProvider.MarkAsPostPrerender(); await base.OnAfterRenderAsync(firstRender); } } }
内容的提问来源于stack exchange,提问作者user2657943
相关产品推荐
相关产品推荐

