Blazor 自定义身份验证提供程序错误
Blazor Custom Authentication Provider Error
我正在创建一个 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
我不确定错误是否清楚,这就是错误的真正所在,或者是否还有其他一些我遗漏的基本步骤。我认为这可能与本地存储的使用有关。
此代码: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 =
new AuthenticationHeaderValue("bearer", token);
GetAuthenticationStateAsync 方法应该有一个 objective:返回身份验证状态 object,这就是为什么您不应该使用它来配置 HttpClient object。您应该从要调用 HttpClient 服务方法的位置执行此操作(从本地存储读取 Jwt 令牌并将其分配给请求的授权 header)。
希望这对您有所帮助...
错误与在加载所有资源之前触发 JS 代码这一事实有关……简而言之。
为了防止它崩溃,我将 Task GetAuthenticationStateAsync() 函数全部包装在一个 try...catch 中并且没有抛出异常。
在 _Host.cshtml 中,更改渲染模式
渲染模式="ServerPrerendered"
到
渲染模式="Server"
我正在创建一个 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
我不确定错误是否清楚,这就是错误的真正所在,或者是否还有其他一些我遗漏的基本步骤。我认为这可能与本地存储的使用有关。
此代码: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 = new AuthenticationHeaderValue("bearer", token);
GetAuthenticationStateAsync 方法应该有一个 objective:返回身份验证状态 object,这就是为什么您不应该使用它来配置 HttpClient object。您应该从要调用 HttpClient 服务方法的位置执行此操作(从本地存储读取 Jwt 令牌并将其分配给请求的授权 header)。
希望这对您有所帮助...
错误与在加载所有资源之前触发 JS 代码这一事实有关……简而言之。
为了防止它崩溃,我将 Task GetAuthenticationStateAsync() 函数全部包装在一个 try...catch 中并且没有抛出异常。
在 _Host.cshtml 中,更改渲染模式
渲染模式="ServerPrerendered"
到 渲染模式="Server"