Blazor本地存储SetItemAsync具有跨页竞争条件



[https://code-maze.com/how-to-secure-blazor-webassembly-with-identityserver4/]

[https://github.com/Blazored/LocalStorage]

我有一个Blazor WASM使用IdentityServer4(上面的指南(,它也使用本地存储。

在我的";RemoteAuthenticatorView";,我把OnLogInSucceed&OnLogOutSuccessed事件。各个事件将执行SetItemAsync&带有本地存储的ClearAsync,其中包含一些额外的用户详细信息。用户详细信息是为了在需要时进行一些次要的数据检索。

目前有2个问题

  1. LocalStorage.SetItemAsync不够快,因为初始化子页时,从本地存储读取将产生空结果。所有存储检索都是在Razor页面的OnInitializedAsync中完成的
  2. OnLogOutSuccessed事件未触发,因此未调用LocalStorage.ClearAsync。使用diff凭据的后续登录将检索以前存储的用户详细信息
<RemoteAuthenticatorView Action="@Action" OnLogInSucceeded="SetClaimsPrincipalData" OnLogOutSucceeded="ClearClaimsPrincipalData">
</RemoteAuthenticatorView>
private async Task SetClaimsPrincipalData()
{
try
{
var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
var user = authState.User;
if (user.Identity.IsAuthenticated)
{
var loggedInAccount = UserData.GetClaimsValue(user);
var loggedInAccountStr = JsonHelper.SerializeString(loggedInAccount);
await this.localStorage.ClearAsync();
await this.localStorage.SetItemAsync(DisplayConfigs.SessionStorageKeyUserData, loggedInAccountStr);
}
}
catch (Exception ex)
{
}
}
private async Task ClearClaimsPrincipalData()
{
try
{
await this.localStorage.ClearAsync();
}
catch (Exception ex)
{
}
}
//=====//
protected override async Task OnInitializedAsync()
{
try
{
var savedUserDataString = await this.localStorage.GetItemAsync<string>(KeyUserData);
this.loggedInAccount = JsonHelper.DeserializeString<LoggedInAccount>(savedUserDataString);
//// Base init
await base.OnInitializedAsync();
}
catch (Exception ex)
{
logger.Error(ex, ex.Message);
}
finally
{
this.StateHasChanged();
}
}

每当我遇到与本地或会话存储的竞争条件时,我最终会创建一个保存/访问数据的服务。该服务使用布尔标志isInitialized,而不是直接访问存储器,而是在读取数据之前等待标志为true

public bool isInitialized = false;
public async Task SetClaimsPrincipalData()
{
// Set LocalStorage
// .
// .
// .
isInitialized = true;
}
public async Task<string> GetClaimsPrincipalData()
{
while (!isInitialized) { await Task.Delay(100); }
return await this.localStorage.GetAsync<string>(DisplayConfigs.SessionStorageKeyUserData);
}

现在,当您调用GetClaimsPrincipalData时,它必须等待SetClaimsPrincipalData完成后才能返回。

最新更新