Blazor Server中CustomAuthStateProvider用户认证过期后未跳转登录页问题
问题原因
Blazor Server的AuthorizeRouteView仅会在两个场景下重新校验用户认证状态:
- 应用初始化/页面刷新触发全量加载时
- 收到
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
相关产品推荐
相关产品推荐

