blazor web程序集中的令牌到期时自动注销



我正在开发一个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);
}
}

这是应用程序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标记包装整个页面,但什么也没发生。

感谢

我使用FilterPipeline检查令牌过期时间,然后在每次请求后检查Blazor WASM上的响应类型。制作了一个函数来清理代码。方法如下:

WebAPI->筛选器->JwtTokenValidateAttribute.cs

public class JwtTokenValidateAttribute : Attribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
string token = context.HttpContext.Request.Headers[HeaderNames.Authorization].ToString().Replace("Bearer ", "");
if (string.IsNullOrWhiteSpace(token))
{
context.Result = new UnauthorizedResult();
return;
}
var tokenManager = context.HttpContext.RequestServices.GetService(typeof(ICustomTokenManager)) as ICustomTokenManager;
if(tokenManager != null && !tokenManager.VerifyToken(token))
{
context.Result = new UnauthorizedResult();
return;
}
}
}

在我们制作属性后,我们可以在控制器上这样调用:

[Route("api/[controller]")]
[ApiVersion("1.0")]
[ApiController]
[JwtTokenValidateAttribute] //here we call the filter pipeline
public class SupplierCompaniesController : ControllerBase
{
//your controller goes here
}

MainLayout.razor:

@code{
public async Task HandleException(Exception exception)
{
if (exception.Message.Contains("401"))
{
await AuthenticationUseCases.Logout();
navigationManager.NavigateTo("/login/Expired", true);
return;
}
//If you use AutoWrapper or other packages, you can send messages here based on your response type, don't forget to parse the values. 
}
}

之后,我们可以在发送请求到API的任何页面中调用HandleErrors,例如:

首先,我们需要用CascadingValue 包裹@body

<CascadingValue Value="this" Name="MainLayout">
@Body
</CascadingValue>

现在我们需要去任何Razor组件,我们将向API 发送请求

@code{
[CascadingParameter(Name = "MainLayout")]
public MainLayout MainLayout { get; set; }
async Task HandleException(Exception e) => await MainLayout.HandleException(e);
async Task OnCreateRow(RoleDto role)
{
try
{
//Your api call goes here
}
catch (Exception e)
{
await MainLayout.HandleException(e);
}
}
}

这个解决方案可能不是最好的,我希望它能帮助你。

如果在Radzen.DialogService中使用@SBU方法,请执行此操作。希望这能帮助使用Radzen的人。

try{
}
catch (Exception ex)
{
//Send back the Exception as the result   
DialogService.Close(ex)
}

然后,在调用方法中执行这样的操作。

var exception = dialogResult as Exception;
if (exception != null && exception.Message.Contains("401"))
{
await HandleException(exception);
}
else
{
}

相关内容

  • 没有找到相关文章

最新更新