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
相关产品推荐
相关产品推荐

