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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 00:57:07