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

Blazor Server中CustomAuthStateProvider用户认证过期后未跳转登录页问题

问题原因

Blazor Server的AuthorizeRouteView仅会在两个场景下重新校验用户认证状态:

  1. 应用初始化/页面刷新触发全量加载时
  2. 收到AuthenticationStateProvider主动推送的状态变更通知时
    你当前的实现只实现了获取状态的逻辑,没有主动通知机制,token过期后没有事件触发AuthorizeRouteView重新拉取最新的认证状态,所以不会触发跳转逻辑,只有刷新页面重新拉取状态时才会生效。

解决步骤

1. 扩展自定义认证状态提供者,增加状态通知入口

修改你的CustomAuthStateProvider,新增公开方法用于主动触发状态更新通知:

public class CustomAuthStateProvider : AuthenticationStateProvider
{
    // 保留你原有代码不变
    private ITokenService TokenService;
    private TokenValidationParameters Validations;

    public CustomAuthStateProvider(ITokenService tokenService, TokenValidationParameters validations)
    {
        TokenService = tokenService;
        Validations = validations;
    }

    public async override Task<AuthenticationState> GetAuthenticationStateAsync()
    {
        try
        {
            var token = TokenService.TryGetToken();
            if (string.IsNullOrEmpty(token)) 
                return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
                
            var handler = new JwtSecurityTokenHandler();
            // 这里校验会自动抛出过期异常,不需要额外判断
            handler.ValidateToken(token, Validations, out var _);
            var identity = new ClaimsIdentity(ServiceExtensions.ParseClaimsFromJwt(token), "JWT");
            return new AuthenticationState(new ClaimsPrincipal(identity));
        }
        catch 
        {
            return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
        }
    }

    // 新增:主动通知认证状态变更
    public void TriggerAuthStateRefresh()
    {
        NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
    }
}

2. 服务注册确认

确保你的Program.cs中是将自定义提供者注册为作用域服务:

// 不要用AddSingleton,必须是Scoped
builder.Services.AddScoped<AuthenticationStateProvider, CustomAuthStateProvider>();

3. 增加触发状态校验的时机

你可以按需选择以下任意一种或多种触发方式:

方式A:路由导航前自动校验(最常用)

在App.razor中注入服务,监听路由变化事件,每次导航前校验认证状态:

@inject NavigationManager NavManager
@inject AuthenticationStateProvider AuthProvider

<!-- 保留你原有Router等代码不变 -->
<CascadingAuthenticationState>
  <Router AppAssembly="@typeof(Program).Assembly">
    <Found Context="routeData">
      <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
        <NotAuthorized>
          <UnauthorizedRedirect />
        </NotAuthorized>
      </AuthorizeRouteView>
    </Found>
    <NotFound>
      <LayoutView Layout="@typeof(MainLayout)">
        <p class="text-muted text-center">抱歉,该地址不存在任何内容。</p>
      </LayoutView>
    </NotFound>
  </Router>
</CascadingAuthenticationState>

@code {
    protected override void OnInitialized()
    {
        NavManager.LocationChanging += OnNavChanging;
    }

    private async void OnNavChanging(object sender, LocationChangingEventArgs e)
    {
        var state = await AuthProvider.GetAuthenticationStateAsync();
        // 认证失效时触发状态更新,自动跳转到登录页
        if (!state.User.Identity?.IsAuthenticated ?? true)
        {
            ((CustomAuthStateProvider)AuthProvider).TriggerAuthStateRefresh();
        }
    }

    public void Dispose()
    {
        NavManager.LocationChanging -= OnNavChanging;
    }
}

方式B:接口请求401时触发

如果你封装了HTTP请求中间件/拦截器,可以在检测到接口返回401状态码时,直接调用TriggerAuthStateRefresh()方法,无需等待用户跳转路由就会触发登录跳转。

方式C:定时后台校验

可以在主布局中加一个定时任务,每隔几分钟校验一次token有效期,发现过期直接触发状态更新,适合有长时间停留在同一个页面需求的场景。


内容的提问来源于stack exchange,提问作者Dumas.DED

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 16:45:04