首页 > 解决方案 > Blazor WebAssembly - 页面刷新时未调用 GetAuthenticationStateAsync()

问题描述

我在我的 Blazor WebAssembly 应用程序中有自定义 AuthenticationStateProvider 并且它没有在页面刷新时调用 GetAuthenticationStateAsync 方法,因此如果用户登录然后他们手动刷新页面 ClaimsPrincipal 是 AuthenticationState 未填充,因此用户无法被授权。我正在使用保存在 cookie 中用于身份验证的 JWT,并且该 cookie 在页面刷新后仍然存在,应用程序只是不调用 GetAuthenticationStateAsync (如果我正确地学习了 blazor,它应该在页面刷新时调用)。

这是我的自定义 AuthenticationStateProvider:

public class CustomAuthenticationStateProvider : AuthenticationStateProvider
{
    private readonly HttpClient _httpClient;
    public CustomAuthenticationStateProvider(
        IHttpClientFactory httpClientFactory)
    {
        _httpClient = httpClientFactory.CreateClient("APIClient");
    }

    public override async Task<AuthenticationState> GetAuthenticationStateAsync()
    {

        //TODO get token from cookie
        var savedToken = "";

        if (string.IsNullOrWhiteSpace(savedToken))
        {
            return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
        }

        return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity(ParseClaimsFromJwt(savedToken), "jwt")));
    }

    public void MarkUserAsAuthenticated(string email)
    {
        var authenticatedUser = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, email) }, "apiauth"));
        var authState = Task.FromResult(new AuthenticationState(authenticatedUser));
        NotifyAuthenticationStateChanged(authState);
    }

    public void MarkUserAsLoggedOut()
    {
        var anonymousUser = new ClaimsPrincipal(new ClaimsIdentity());
        var authState = Task.FromResult(new AuthenticationState(anonymousUser));
        NotifyAuthenticationStateChanged(authState);
    }
}

编辑:它一直在调用 GetAuthenticationStateAsync 方法,这只是令人困惑,因为我在调试器中并且它从未在该方法内达到我的断点,这是我看到其他人的问题(仍然不确定为什么会这样)。

标签: c#.netauthenticationblazorblazor-webassembly

解决方案


这取决于你在哪里打电话GetAuthenticationStateAsync
即在BlazorHero项目中,此调用存在于MainLayout.razor中:

</NotAuthorized>
    <Authorized>
        @(LoadDataAsync())
        <MudLayout RightToLeft="@_rightToLeft">

MainLayout.razor.cs

private async Task LoadDataAsync()
    {
        var state = await _stateProvider.GetAuthenticationStateAsync();
        var user = state.User;
        if (user == null) return;

所以我认为您需要检查它的名称。

每次加载页面时都会呈现MainLayout

更好的解决方案(更清洁)是添加以下代码AfterRender

protected override async Task OnAfterRenderAsync(bool firstRender)
{
    if (firstRender)
    {
        await LoadDataAsync();
    }
}

推荐阅读