身份验证状态提供程序不在自定义消息处理程序中工作

Authentication state provider not working inside custom message handler

自定义消息处理程序

如果不能更新token,预计会被注销

protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
    CancellationToken cancellationToken)
{
    await SetAuthorizationHeader(request);
    var response = await base.SendAsync(request, cancellationToken);

    if (IsRefreshRequired(response))
    {
        var tokenRefreshed = await _authService.TryRefreshTokenAsync();

        if (tokenRefreshed)
        {
            await SetAuthorizationHeader(request);
            return await base.SendAsync(request, cancellationToken);
        }

        await _authService.LogoutAsync();
        _navigationManager.NavigateTo(Routes.App.Login);
    }

    return response;
}

private async Task SetAuthorizationHeader(HttpRequestMessage request)
{
    var accessToken = await _localStorage.GetItemAsync<string>(Auth.AccessToken);

    if (!string.IsNullOrWhiteSpace(accessToken))
    {
        request.Headers.Authorization = new AuthenticationHeaderValue(Auth.Scheme, accessToken);
    }
}

认证服务

public async Task LogoutAsync()
{
    await RemoveTokensAsync();
    AuthStateProvider.NotifyAuthenticationStateChanged();
}

自定义身份验证状态提供程序

public override async Task<AuthenticationState> GetAuthenticationStateAsync()
{
    var accessToken = await _localStorage.GetItemAsync<string>(Auth.AccessToken);

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

    var claims = TokenParser.ParseClaims(accessToken);
    var user = new ClaimsPrincipal(new ClaimsIdentity(claims, Auth.AuthType));

    return new AuthenticationState(user);
}

public void NotifyAuthenticationStateChanged()
{
    NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
}

调用 LogoutAsync 方法后,它成功将我重定向到登录页面,但它没有更新 header:

如果我要更新页面或者我不是从处理程序而是从 razor 组件调用 LogoutAsync 都可以工作:

而且它不依赖于我使用的 http 客户端。

根据评论。感谢@enet 和@HenkHolterman。

根本原因: StateHasChanged() 逻辑不传播 'out and up'。注销是调用内部组件导致的,LoginDisplay组件不参与默认更新

解决方法: UI 重新渲染。没有单一的方法可以做到。

在我的例子中我改变了
_navigationManager.NavigateTo(Routes.App.Login);_navigationManager.NavigateTo(Routes.App.Logout);

因此,注销页面会触发更改组件级别的身份验证状态逻辑,然后将用户重定向到登录页面。

其他方法 -- 在调用 NotifyAuthenticationStateChanged 后应从 LogoutAsync 中触发的消息处理程序中定义事件处理程序。此事件的订阅者应该是 re-renders.

的 MainLayout 组件