身份验证状态提供程序不在自定义消息处理程序中工作
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 组件
自定义消息处理程序
如果不能更新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 组件