You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blazor WASM JWT:如何在MainLayout中获取认证状态

.NET 8 Blazor WebAssembly JWT认证:布局组件授权状态异常解决

问题场景

在.NET 8 Blazor WebAssembly项目中配置JWT认证时,带交互式渲染模式的页面组件里的AuthorizeView能正常返回Authorized或NotAuthorized状态,但MainLayout布局组件中的AuthorizeView始终返回NotAuthorized。排查确认是MainLayout未以交互式方式渲染导致。

核心原因

自定义的JwtAuthenticationStateProvider依赖客户端的IJSRuntime和本地存储(Blazored.LocalStorage)读取JWT Token。默认情况下,布局组件以静态渲染模式运行,无法访问客户端资源,因此GetAuthenticationStateAsync方法会直接返回未授权的认证状态。

解决方案

以下两种方法均可解决问题,按需选择:

方法一:直接为MainLayout指定交互式渲染模式

在MainLayout.razor顶部添加@rendermode指令,强制布局以客户端交互式模式运行:

@using Microsoft.AspNetCore.Components.Authorization
@inherits LayoutComponentBase
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))

<CascadingAuthenticationState>
    <AuthorizeView>
        <Authorized>
            Authorized
        </Authorized>
        <NotAuthorized>
            NotAuthorized
        </NotAuthorized>
    </AuthorizeView>
    @* 保留原有布局内容 *@
    @Body
</CascadingAuthenticationState>
  • 设置prerender: false可避免预渲染阶段的状态不一致;若需预渲染,可改为true,但需确保预渲染逻辑不依赖客户端资源。

方法二:在Routes.razor中统一指定布局渲染模式

修改Routes.razor中的AuthorizeRouteView和LayoutView,为布局添加RenderMode属性:

@using Microsoft.AspNetCore.Components.Authorization
<CascadingAuthenticationState>
    <Router AppAssembly="@typeof(App).Assembly">
        <Found Context="routeData">
            <AuthorizeRouteView RouteData="@routeData" 
                DefaultLayout="@typeof(Layout.MainLayout)"
                RenderMode="@(new InteractiveWebAssemblyRenderMode(prerender: false))" />
        </Found>
        <NotFound>
            <LayoutView Layout="@typeof(Layout.MainLayout)"
                RenderMode="@(new InteractiveWebAssemblyRenderMode(prerender: false))">
                <p>Sorry, there's nothing at this address.</p>
            </LayoutView>
        </NotFound>
    </Router>
</CascadingAuthenticationState>

此方式无需修改布局文件,适合统一管理布局的渲染模式。

关键代码验证

自定义JwtAuthenticationStateProvider的核心逻辑无需修改,当布局以交互式模式运行时,_JSRuntime会是IJSInProcessRuntime实例,从而正常读取本地存储中的Token:

public sealed override async Task<AuthenticationState> GetAuthenticationStateAsync()
{
    if (_JSRuntime is not IJSInProcessRuntime)
        return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
    
    var token = await _localStorage.GetItemAsync<string>(TokenKey);

    if (string.IsNullOrEmpty(token))
        return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));

    var user = new ClaimsPrincipal(new ClaimsIdentity(ParseClaimsFromJwt(token), "jwt"));
    return new AuthenticationState(user);
}

内容的提问来源于stack exchange,提问作者Mikołaj Szczepek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 19:54:54