【发布时间】:2021-08-23 10:11:44
【问题描述】:
我正在开发一个 blazor Web 程序集应用程序。我创建了登录和注销方法,对于令牌到期时间的注销,我将到期日期存储在本地存储中。但检查此日期需要加载整页。我想自动检查那个日期,或者当我打开一个页面并重定向到登录页面时,如果那个时间过去了。
这是我的 CustomAuthenticationStateProvider.cs
public class CustomAuthenticationStateProvider : AuthenticationStateProvider
{
private readonly HttpClient _httpClient;
private readonly ILocalStorageService _localStorageService;
public CustomAuthenticationStateProvider(HttpClient httpClient, ILocalStorageService localStorageService)
{
_httpClient = httpClient;
_localStorageService = localStorageService;
}
private async Task<bool> TokenExpired()
{
bool expire = false;
var exist = await _localStorageService.ContainKeyAsync(ClientConstantKeys.AppTokenExpireDate);
if (exist)
{
var dateString = await _localStorageService.GetItemAsync<string>(ClientConstantKeys.AppTokenExpireDate);
var date = DateTime.Parse(dateString);
if (DateTime.Now >= date)
{
expire = true;
await NotifyUserLoggedOut();
}
}
else
{
expire = true;
await NotifyUserLoggedOut();
}
return expire;
}
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
{
var token = await _localStorageService.GetItemAsync<string>(ClientConstantKeys.AppToken);
var expired = await TokenExpired();
if (string.IsNullOrEmpty(token) || expired)
{
return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
}
var claimsValueTypes = await _localStorageService.GetItemAsync<Dictionary<string, object>>(ClientConstantKeys.AppClaims);
var claims = ClaimParser.GetClaims(claimsValueTypes);
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", token);
return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity(claims, "jwtAuthType")));
}
public void NotifyUserLogIn(List<Claim> claims)
{
var authState = Task.FromResult(new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity(claims, "jwtAuthType"))));
base.NotifyAuthenticationStateChanged(authState);
}
public async Task NotifyUserLoggedOut()
{
var authState = Task.FromResult(new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity())));
await _localStorageService.RemoveItemAsync(ClientConstantKeys.AppToken);
await _localStorageService.RemoveItemAsync(ClientConstantKeys.AppClaims);
await _localStorageService.RemoveItemAsync(ClientConstantKeys.AppTokenExpireDate);
_httpClient.DefaultRequestHeaders.Authorization = null;
base.NotifyAuthenticationStateChanged(authState);
}
}
这是 App.Razor
<CascadingAuthenticationState>
<Router AppAssembly="@typeof(Program).Assembly" PreferExactMatches="@true">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
<NotAuthorized>
<AccessDenied></AccessDenied>
</NotAuthorized>
</AuthorizeRouteView>
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<PageNotFound></PageNotFound>
</LayoutView>
</NotFound>
</Router>
</CascadingAuthenticationState>
当我点击登录或注销时一切正常,但我想自动检查过期时间。
我尝试用 AuthorizedView 标签包裹我的整个页面,但没有任何反应。
谢谢
【问题讨论】:
-
你找到解决办法了吗?
-
@SBU 也许这不是一个好主意,但我创建了一个没有任何标记的组件,并且在它的 OnInitializedAsync 方法中检查令牌过期时间,如果令牌无效,请调用 NotifyUserLoggedOut 方法并导航到登录页面。在打开令牌之前,我必须将此组件添加到要检查令牌的每个组件中。
-
其实我也有类似的想法。我正在检查返回 401 的过滤器管道上的令牌过期。我在 MainLayout 上创建了一个函数来处理错误并通过 CascadingParameter 将该函数发送到其他组件。如果捕获状态捕获 401,我会注销用户并重定向到 Login。
-
@SUB 是的,看来他们的想法是一样的,我试试,谢谢
标签: c# asp.net-web-api blazor blazor-webassembly