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

时间:2020-09-10 16:47:38

标签: c# blazor blazor-webassembly

自定义消息处理程序

如果令牌无法更新,则预计将注销。

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方法后,它成功将我重定向到“登录”页面,但未更新标题:

enter image description here

如果我要更新页面,或者不是从处理程序而是从剃刀组件中调用LogoutAsync,那么所有方法都将起作用:

enter image description here

它也不取决于我使用的http客户端。

1 个答案:

答案 0 :(得分:1)

基于评论。谢谢@enet和@HenkHolterman。

根本原因StateHasChanged()逻辑不会“向外传播”。注销是由内部组件上的调用引起的,LoginDisplay组件不参与默认更新。

解决方案:用户界面重新呈现。没有唯一的方法。

就我而言,我改变了
_navigationManager.NavigateTo(Routes.App.Login);_navigationManager.NavigateTo(Routes.App.Logout);

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

另一种方式-在消息处理程序中定义一个事件处理程序,该事件处理程序应在调用NotifyAuthenticationStateChanged之后从LogoutAsync内部触发。此事件的订阅者应该是MainLayout组件,该组件会重新呈现。