Blazor不刷新页面时AuthorizeView未更新的问题解决
问题描述
我的StickyMenu组件中使用了以下代码:
<AuthorizeView> <NotAuthorized> Not Authorized </NotAuthorized> <Authorized> Authorized @(context.User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value) </Authorized> </AuthorizeView>
配置的CustomAuthStateProvider代码如下:
public class CustomAuthStateProvider : AuthenticationStateProvider { private readonly ProtectedSessionStorage _sessionStorage; private ClaimsPrincipal _anonymous = new ClaimsPrincipal(new ClaimsIdentity()); public CustomAuthStateProvider(ProtectedSessionStorage sessionStorage) { _sessionStorage = sessionStorage; } public async Task<Utenti?> GetUser() { var userSessionStorageResult = await _sessionStorage.GetAsync<Utenti>(Constants.sessionStorageUser); return userSessionStorageResult.Success ? userSessionStorageResult.Value : null; } public override async Task<AuthenticationState> GetAuthenticationStateAsync() { try { Utenti? userSession = await GetUser(); if (userSession == null) { return await Task.FromResult(new AuthenticationState(_anonymous)); } else { var claimsPrincipal = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim> { new Claim(ClaimTypes.Name, userSession?.Nome ?? String.Empty), new Claim(ClaimTypes.Email, userSession?.email ?? String.Empty), new Claim(ClaimTypes.NameIdentifier, userSession.IdUtente.ToString()) }, "CustomAuth")); return await Task.FromResult(new AuthenticationState(claimsPrincipal)); } } catch { return await Task.FromResult(new AuthenticationState(_anonymous)); } } public void UpdateAuthenticationState(Utenti parUser) { ClaimsPrincipal claimsPrincipal; if (parUser != null) { _sessionStorage.SetAsync(Constants.sessionStorageUser, parUser); claimsPrincipal = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim> { new Claim(ClaimTypes.Name, parUser.Nome), new Claim(ClaimTypes.Email, parUser.email), new Claim(ClaimTypes.NameIdentifier, parUser.IdUtente.ToString()) })); } else { _sessionStorage.DeleteAsync(Constants.sessionStorageUser); claimsPrincipal = _anonymous; } NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(claimsPrincipal))); } }
登录页的Login方法:
public void Login() { Utenti u = Utenti.Login(Username, StringUtil.encryptpass(Password)); if (u != null) { var customAuthStateProvider = (CustomAuthStateProvider)AuthenticationStateProvider; customAuthStateProvider.UpdateAuthenticationState(u); NavigationManager.NavigateTo("/",true); } }
此时菜单能正常显示Authorized及用户名。
但在添加商品到购物车时,调用以下方法创建临时用户并更新StickyMenu组件:
public async void AddToCart() { Utenti ut = Utenti.Login("email", StringUtil.encryptpass("password")); if (ut.IdUtente > 0) { var customAuthStateProvider = (CustomAuthStateProvider)AuthenticationStateProvider; customAuthStateProvider.UpdateAuthenticationState(ut); } }
如果不调用NavigationManager.NavigateTo(someurl,true)刷新页面,AuthorizeView就不会更新,请问该如何解决?
解决方案
问题根源有两处:
- 异步操作未等待:
UpdateAuthenticationState里调用的_sessionStorage.SetAsync和_sessionStorage.DeleteAsync是异步方法,但未使用await等待执行完成,会导致会话存储更新与认证状态通知不同步。 - 认证类型不匹配:
GetAuthenticationStateAsync中创建ClaimsIdentity时指定了"CustomAuth"认证类型,但UpdateAuthenticationState里创建的ClaimsIdentity未设置该类型,导致AuthorizeView无法正确识别用户身份状态。
修改UpdateAuthenticationState方法:
public async Task UpdateAuthenticationState(Utenti parUser) { ClaimsPrincipal claimsPrincipal; if (parUser != null) { await _sessionStorage.SetAsync(Constants.sessionStorageUser, parUser); claimsPrincipal = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim> { new Claim(ClaimTypes.Name, parUser.Nome), new Claim(ClaimTypes.Email, parUser.email), new Claim(ClaimTypes.NameIdentifier, parUser.IdUtente.ToString()) }, "CustomAuth")); } else { await _sessionStorage.DeleteAsync(Constants.sessionStorageUser); claimsPrincipal = _anonymous; } NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(claimsPrincipal))); }
同时修改AddToCart方法,改为异步方法并等待认证状态更新完成:
public async Task AddToCart() { Utenti ut = Utenti.Login("email", StringUtil.encryptpass("password")); if (ut.IdUtente > 0) { var customAuthStateProvider = (CustomAuthStateProvider)AuthenticationStateProvider; await customAuthStateProvider.UpdateAuthenticationState(ut); } }
修改后,无需刷新页面,AuthorizeView就能自动更新显示认证状态。
内容的提问来源于stack exchange,提问作者Martina
相关产品推荐
相关产品推荐

