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

Blazor Server自定义AuthenticationStateProvider:NotAuthorized失效及全局授权问题

Blazor Server 全局认证重定向问题解决

问题分析

  • 布局组件(如MainLayout)上添加[Authorize]属性无法触发AuthorizeRouteView的NotAuthorized模板,因为AuthorizeRouteView仅对路由匹配的页面组件生效,布局是页面渲染后嵌套的,不参与路由级别的授权逻辑。
  • 自定义AuthenticationStateProvider中存在一处不一致:UpdateAuthenticationStateAsync方法创建ClaimsIdentity时未指定认证类型("SmartMISAuth"),与GetAuthenticationStateAsync中的实现不统一,可能导致身份验证状态判断异常。

解决方案

1. 修复自定义AuthenticationStateProvider的一致性问题

修改UpdateAuthenticationStateAsync方法中创建ClaimsIdentity的代码,添加认证类型参数,确保与GetAuthenticationStateAsync逻辑一致:

public async Task UpdateAuthenticationStateAsync(AccountInfo accountInfo)
{
    ClaimsPrincipal claimsPrincipal;

    if (accountInfo != null)
    {
        await _sessionStorage.SetAsync("_accountSession", accountInfo);

        var claims = new List<Claim>();
        claims.Add(new Claim("AccountID", accountInfo.AccountID));
        claims.Add(new Claim("AccountType", accountInfo.AccountType));
        claims.Add(new Claim(ClaimTypes.Name, accountInfo.FullName));
        claims.Add(new Claim(ClaimTypes.MobilePhone, accountInfo.PhoneNumber));

        // 添加认证类型,与GetAuthenticationStateAsync保持统一
        claimsPrincipal = new ClaimsPrincipal(new ClaimsIdentity(claims, "SmartMISAuth"));
    }
    else
    {
        await _sessionStorage.DeleteAsync("_accountSession");
        claimsPrincipal = _anonymous;
    }

    NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(claimsPrincipal)));
}

2. 实现全局认证重定向(推荐方案)

通过在App.razor中使用AuthorizeView包裹路由匹配后的内容,实现全局范围的认证检查,无需给每个页面单独添加[Authorize]属性:

修改后的App.razor代码:

<CascadingAuthenticationState>
    <Router AppAssembly="@typeof(App).Assembly" AdditionalAssemblies="@_loadedAssemblies">
        <Found Context="routeData">
            <AuthorizeView>
                <Authorized>
                    <!-- 已认证用户正常渲染页面 -->
                    <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
                        <NotAuthorized>
                            <!-- 处理页面级别的授权失败(如角色权限不足) -->
                            <div class="alert alert-danger">您没有权限访问此页面</div>
                        </NotAuthorized>
                        <Authorizing>
                            <span class="persianFontSans">Authorizing ...</span>
                        </Authorizing>
                    </AuthorizeRouteView>
                    <FocusOnNavigate RouteData="@routeData" Selector="h1" />
                </Authorized>
                <NotAuthorized>
                    <!-- 未认证用户直接跳转到登录页面 -->
                    <RedirectToLoginPage />
                </NotAuthorized>
                <Authorizing>
                    <span class="persianFontSans">Authorizing ...</span>
                </Authorizing>
            </AuthorizeView>
        </Found>
        <NotFound>
            <PageTitle>The page not found</PageTitle>
            <LayoutView Layout="@typeof(MainLayout)">
                <NotFound />
            </LayoutView>
        </NotFound>
    </Router>
</CascadingAuthenticationState>

3. 确保RedirectToLoginPage组件正确实现重定向

RedirectToLoginPage组件需要处理导航逻辑,并保存当前页面URL以便登录后返回:

@inject NavigationManager NavigationManager

@code {
    protected override void OnInitialized()
    {
        // 保存当前访问的URL,登录后可跳转回来
        var returnUrl = NavigationManager.Uri;
        NavigationManager.NavigateTo($"/login?returnUrl={Uri.EscapeDataString(returnUrl)}");
    }
}

内容的提问来源于stack exchange,提问作者hdv212

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 01:46:05