本地存储上的自定义 AuthenticationStateProviderService 错误

问题描述 投票:0回答:1

我有一个 CustomAuthenticationStateProviderService。起初我使用常量来存储 JWTToken,但现在我想切换到使用本地存储。

public class Constants
{
    public static string JWTToken { get; set; } = "";
}

public class CustomAuthenticationStateProviderService : AuthenticationStateProvider
{
    private readonly ClaimsPrincipal anonymous = new(new ClaimsIdentity());
    private readonly ProtectedLocalStorage localStorage;

    public CustomAuthenticationStateProviderService(ProtectedLocalStorage localStorage)
    {
        this.localStorage = localStorage;
    }

    public async override Task<AuthenticationState> GetAuthenticationStateAsync()
    {
        try
        {
            var token = await localStorage.GetAsync<string>("headerToken");

            
            if (string.IsNullOrWhiteSpace(Constants.JWTToken))
                return await Task.FromResult(new AuthenticationState(anonymous));

            var claims = JWTService.DecryptToken(Constants.JWTToken);
            if (claims == null) return await Task.FromResult(new AuthenticationState(anonymous));

            var claimsPrincipal = SetClaimPrincipal(claims);
            return await Task.FromResult(new AuthenticationState(claimsPrincipal));
        }
        catch (Exception ex)
        {
            return await Task.FromResult(new AuthenticationState(anonymous));
        }
    }
}

我在类中还有其他方法,但这是迄今为止我开始使用本地存储的唯一方法。在到达应用程序的第一页之前会抛出一个错误,即

'JavaScript interop calls cannot be issued at this time. This is because the component is being statically rendered. When prerendering is enabled, JavaScript interop calls can only be performed during the OnAfterRenderAsync lifecycle method.'

我知道它希望我使用 OnAfterRenderAsync 方法,但这种情况发生在它进入我的任何页面之前,所以这没有帮助。另外,出于逻辑原因,我需要在 OnInitialized 中使用它,这就是为什么我的页面使用

@rendermode @(new InteractiveServerRenderMode(false))

我用 try catch 包围了获取本地存储,该问题修复了。我找到了一个答案,说这种行为是由我在程序中的

builder.Services.AddCascadingAuthenticationState();
引起的。cs

try
{
    var token = await localStorage.GetAsync<string>("headerToken");
}
catch (InvalidOperationException)
{
}

这解决了第一个问题,但随后我收到一个新错误:

JavaScript interop calls cannot be issued at this time. This is because the circuit has disconnected and is being disposed.

我应该如何修复这些错误以使本地存储按预期工作?

javascript c# asp.net-core jwt blazor
1个回答
0
投票

您遇到此错误是因为您尝试在应用程序初始渲染阶段访问本地存储。

在这种情况下,

OnAfterRenderAsync
似乎不是解决您问题的方法,因为一旦组件处于交互状态,就设置一个标志,然后调用必要的逻辑来更新身份验证状态。

protected override async Task OnAfterRenderAsync(bool firstRender)
{
    if (firstRender)
    {
        var token = await localStorage.GetAsync<string>("headerToken");
        await UpdateAuthenticationState(token.Value);
    }
}

之后,在您的

CustomAuthenticationStateProviderService
中创建一个方法,该方法处理基于本地存储中的令牌更新身份验证状态的逻辑。该方法可以从
OnAfterRenderAsync

调用
public async Task UpdateAuthenticationState(string token)
{
    if (string.IsNullOrWhiteSpace(token))
    {
        NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(anonymous)));
    }
    else
    {
        var claims = JWTService.DecryptToken(token);
        if (claims == null)
        {
            NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(anonymous)));
        }
        else
        {
            var claimsPrincipal = SetClaimPrincipal(claims);
            NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(claimsPrincipal)));
        }
    }
}

不要忘记删除对 Constants.JWTToken 的依赖

© www.soinside.com 2019 - 2024. All rights reserved.