Blazor自定义身份验证提供程序错误

时间:2020-04-11 01:50:35

标签: c# asp.net-core blazor blazor-server-side blazor-client-side

我正在创建一个Blazor UI应用程序以与API通讯。目前,我正在尝试为此工作获取自定义提供程序,但出现了一些错误。

这是客户AuthenticationStateProvider

public class APIAuthenticationStateProvider : AuthenticationStateProvider
{
    private readonly HttpClient _httpClient;
    private readonly ILocalStorageService _localStorage;
    public APIAuthenticationStateProvider(HttpClient httpClient, ILocalStorageService localStorage)
    {
        _httpClient = httpClient;
        _localStorage = localStorage;
    }
    public override async Task<AuthenticationState> GetAuthenticationStateAsync()
    {
        var token = await _localStorage.GetItemAsync<string>("authToken");

        if (string.IsNullOrWhiteSpace(token))
        {
            return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
        }

        _httpClient.DefaultRequestHeaders.Authorization =
            new AuthenticationHeaderValue("bearer", token);

        var claims = ParseClaims(token);

        return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity(claims,"jwt")));
    }
}

Startup.cs文件中的“我的配置服务”功能如下

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();
    services.AddServerSideBlazor();
    services.AddBlazoredLocalStorage();
    services.AddScoped<AuthenticationStateProvider, APIAuthenticationStateProvider>();
    services.AddTransient<IAuthRepository, AuthRepository>();
    services.AddHttpClient();
}

执行死刑时,出现以下异常

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

Microsoft.AspNetCore.Components.Server.Circuits.RemoteJSRuntime.BeginInvokeJS(long asyncHandle, string identifier, string argsJson)
Microsoft.JSInterop.JSRuntime.InvokeAsync<TValue>(string identifier, CancellationToken cancellationToken, object[] args)
Microsoft.JSInterop.JSRuntime.InvokeWithDefaultCancellation<T>(string identifier, object[] args)
System.Threading.Tasks.ValueTask<TResult>.get_Result()
System.Runtime.CompilerServices.ValueTaskAwaiter<TResult>.GetResult()
Blazored.LocalStorage.LocalStorageService.GetItemAsync<T>(string key)
BookStore_UI.Providers.APIAuthenticationStateProvider.GetAuthenticationStateAsync() in APIAuthenticationStateProvider.cs

我不确定错误是否很明显,而这正是错误的真正出处,或者我是否缺少其他一些基础步骤。我认为这可能与使用本地存储有关。

3 个答案:

答案 0 :(得分:1)

此代码:var token = await _localStorage.GetItemAsync<string>("authToken");在JavaScript不可用时执行。在尝试访问本地存储时,请查找文档如何处理此类情况。他们专门展示了如何完成这项任务。

您的ConfigureServices应该看起来像这样:

services.AddRazorPages();
services.AddServerSideBlazor();
services.AddBlazoredLocalStorage();
services.AddHttpClient();
services.AddScoped<APIAuthenticationStateProvider>();
services.AddScoped<AuthenticationStateProvider>(provider => 
       provider.GetRequiredService<APIAuthenticationStateProvider>());
services.AddTransient<IAuthRepository, AuthRepository>();

_httpClient.DefaultRequestHeaders.Authorization = 新的AuthenticationHeaderValue(“ bearer”,令牌);

GetAuthenticationStateAsync方法应该有一个目标:返回Authentication State对象,这就是为什么您不应该使用它来配置HttpClient对象的原因。您应该从要调用HttpClient服务方法的位置进行此操作(从本地存储中读取Jwt令牌并将其分配给请求的Authorization标头)。

希望这对您有帮助...

答案 1 :(得分:1)

在_Host.cshtml中,更改渲染模式

render-mode =“ ServerPrerendered”

到 render-mode =“ Server”

答案 2 :(得分:0)

错误与以下事实有关:简而言之,在加载所有资源之前已触发JS代码。

为了防止崩溃,我将Task GetAuthenticationStateAsync()函数全部包装在try ... catch中,并且未引发异常。