未注册身份验证 AuthenticationStateProvider 的 Blazor Wasm 托管预渲染
Posted
技术标签:
【中文标题】未注册身份验证 AuthenticationStateProvider 的 Blazor Wasm 托管预渲染【英文标题】:Blazor Wasm Hosted Prerender with Authentication AuthenticationStateProvider not registered 【发布时间】:2021-03-02 03:09:11 【问题描述】:我有一个使用 Blazor WebAssembly Hosted with Authentication 的开箱即用的 VS 模板,并将其转换为使用 PreRendering。但是,这样做看起来有很多服务包含在客户端中,而在服务器端没有提供。这是一个例外
处理请求时发生未处理的异常。 InvalidOperationException:无法为属性提供值 'AuthenticationStateProvider' 类型 'Microsoft.AspNetCore.Components.Authorization.CascadingAuthenticationState'。 没有注册类型的服务 'Microsoft.AspNetCore.Components.Authorization.AuthenticationStateProvider'。 Microsoft.AspNetCore.Components.ComponentFactory+c__DisplayClass6_0.g__Initialize|2(IServiceProvider serviceProvider,IComponent 组件)
堆栈查询 Cookie 标头路由 InvalidOperationException:不能 为类型上的属性“AuthenticationStateProvider”提供一个值 'Microsoft.AspNetCore.Components.Authorization.CascadingAuthenticationState'。 没有注册类型的服务 'Microsoft.AspNetCore.Components.Authorization.AuthenticationStateProvider'。 Microsoft.AspNetCore.Components.ComponentFactory+c__DisplayClass6_0.g__Initialize|2(IServiceProvider serviceProvider,IComponent 组件) Microsoft.AspNetCore.Components.ComponentFactory.PerformPropertyInjection(IServiceProvider serviceProvider,IComponent 实例) Microsoft.AspNetCore.Components.ComponentFactory.InstantiateComponent(IServiceProvider 服务提供者,类型组件类型) Microsoft.AspNetCore.Components.RenderTree.Renderer.InstantiateChildComponentOnFrame(参考 RenderTreeFrame 框架,int parentComponentId) Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewComponentFrame(参考 DiffContext diffContext, int frameIndex) Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewSubtree(参考 DiffContext diffContext, int frameIndex) Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InsertNewFrame(参考 DiffContext diffContext, int newFrameIndex) Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForRange(参考 DiffContext diffContext, int oldStartIndex, int oldEndIndexExcl, int newStartIndex, int newEndIndexExcl) Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.ComputeDiff(渲染器 renderer, RenderBatchBuilder batchBuilder, int componentId, ArrayRange oldTree, ArrayRange 新树) Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder batchBuilder, RenderFragment (renderFragment) Microsoft.AspNetCore.Components.RenderTree.Renderer.RenderInExistingBatch(RenderQueueEntry 渲染队列条目) Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue() Microsoft.AspNetCore.Components.Rendering.htmlRenderer.HandleException(异常 例外) Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue() Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessPendingRender() Microsoft.AspNetCore.Components.RenderTree.Renderer.AddToRenderQueue(int componentId, RenderFragment (renderFragment) Microsoft.AspNetCore.Components.ComponentBase.StateHasChanged() Microsoft.AspNetCore.Components.ComponentBase.CallOnParametersSetAsync() Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync() Microsoft.AspNetCore.Components.Rendering.HtmlRenderer.HandleException(异常 例外) Microsoft.AspNetCore.Components.RenderTree.Renderer.AddToPendingTasks(任务 任务) Microsoft.AspNetCore.Components.Rendering.ComponentState.SetDirectParameters(ParameterView 参数) Microsoft.AspNetCore.Components.RenderTree.Renderer.RenderRootComponentAsync(int componentId, ParameterView 初始参数) Microsoft.AspNetCore.Components.Rendering.HtmlRenderer.CreateInitialRenderAsync(类型 componentType, ParameterView 初始参数) Microsoft.AspNetCore.Components.Rendering.HtmlRenderer.RenderComponentAsync(类型 componentType, ParameterView 初始参数) Microsoft.AspNetCore.Components.Rendering.RendererSynchronizationContext+c__11+
d.MoveNext() Microsoft.AspNetCore.Mvc.ViewFeatures.StaticComponentRenderer.PrerenderComponentAsync(ParameterView 参数,HttpContext httpContext,类型组件类型) Microsoft.AspNetCore.Mvc.ViewFeatures.ComponentRenderer.PrerenderedWebAssemblyComponentAsync(HttpContext 上下文、类型类型、ParameterView parametersCollection) Microsoft.AspNetCore.Mvc.ViewFeatures.ComponentRenderer.RenderComponentAsync(ViewContext viewContext, 类型 componentType, RenderMode renderMode, object 参数) Microsoft.AspNetCore.Mvc.TagHelpers.ComponentTagHelper.ProcessAsync(TagHelperContext 上下文,TagHelperOutput 输出) Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner.g__Awaited|0_0(任务 任务, TagHelperExecutionContext executionContext, int i, int count) BBQFriend.Server.Pages.Pages__Host.b__9_1() 在 _Host.cshtml + Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperExecutionContext.SetOutputContentAsync() BBQFriend.Server.Pages.Pages__Host.ExecuteAsync() Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageCoreAsync(IRazorPage 页面,ViewContext 上下文) Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageAsync(IRazorPage 页面,ViewContext 上下文,bool invokeViewStarts) Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderAsync(ViewContext 语境) Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, 字符串 contentType, Nullable statusCode) Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, 字符串 contentType, Nullable statusCode) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|29_0 (ResourceInvoker 调用者,Task lastTask,State next, 范围作用域,对象状态,bool isCompleted) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed 语境) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext (ref State next, ref Scope scope, ref object state, ref 布尔已完成) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters() Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|24_0(ResourceInvoker 调用者,任务 lastTask,下一个状态,作用域范围,对象状态,布尔 完成了) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed 语境) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(参考状态 接下来,ref Scope 范围,ref 对象状态,ref bool isCompleted) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync() Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|17_0(ResourceInvoker 调用者、任务任务、IDisposable 范围) Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask|6_0(端点 端点、任务 requestTask、ILogger 记录器) Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext 语境) Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext 语境) IdentityServer4.Hosting.IdentityServerMiddleware.Invoke(HttpContext 上下文、IEndpointRouter 路由器、IUserSession 会话、IEventService 事件,IBackChannelLogoutService backChannelLogoutService) IdentityServer4.Hosting.MutualTlsEndpointMiddleware.Invoke(HttpContext 上下文,IAuthenticationSchemeProvider 方案) Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext 上下文)IdentityServer4.Hosting.BaseUrlMiddleware.Invoke(HttpContext 语境) Microsoft.AspNetCore.Builder.Extensions.MapWhenMiddleware.Invoke(HttpContext 语境) Microsoft.AspNetCore.Builder.Extensions.MapMiddleware.Invoke(HttpContext 语境) Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.MigrationsEndPointMiddleware.Invoke(HttpContext 语境) Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext 上下文)
我可以在Server startup.cs中注册哪些服务来注册必要的服务?
【问题讨论】:
【参考方案1】:我也遇到过同样的问题,我在TheIdServer 通过注册和存根一些服务解决了这个问题:
services.AddRemoteAuthentication<RemoteAuthenticationState, RemoteUserAccount, OidcProviderOptions>();
services.AddScoped<AuthenticationStateProvider, RemoteAuthenticationService>()
.AddScoped<SignOutSessionStateManager>()
.AddTransient<IAccessTokenProvider, AccessTokenProvider>()
.AddTransient<Microsoft.JSInterop.IJSRuntime, JSRuntime>();
RemoteAuthenticationService.cs
using Microsoft.AspNetCore.Components.Server;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using System.Threading.Tasks;
namespace Aguacongas.TheIdServer.Services
public class RemoteAuthenticationService : ServerAuthenticationStateProvider, IRemoteAuthenticationService<RemoteAuthenticationState>
public Task<RemoteAuthenticationResult<RemoteAuthenticationState>> CompleteSignInAsync(RemoteAuthenticationContext<RemoteAuthenticationState> context)
return Success(context);
public Task<RemoteAuthenticationResult<RemoteAuthenticationState>> CompleteSignOutAsync(RemoteAuthenticationContext<RemoteAuthenticationState> context)
return Success(context);
public Task<RemoteAuthenticationResult<RemoteAuthenticationState>> SignInAsync(RemoteAuthenticationContext<RemoteAuthenticationState> context)
return Success(context);
public Task<RemoteAuthenticationResult<RemoteAuthenticationState>> SignOutAsync(RemoteAuthenticationContext<RemoteAuthenticationState> context)
return Success(context);
private static Task<RemoteAuthenticationResult<RemoteAuthenticationState>> Success(RemoteAuthenticationContext<RemoteAuthenticationState> context)
return Task.FromResult(new RemoteAuthenticationResult<RemoteAuthenticationState>
State = context.State,
Status = RemoteAuthenticationStatus.Success
);
AccessTokenProvider.cs
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using System;
using System.Threading.Tasks;
namespace Aguacongas.TheIdServer.Services
public class AccessTokenProvider : IAccessTokenProvider
public ValueTask<AccessTokenResult> RequestAccessToken()
throw new NotImplementedException();
public ValueTask<AccessTokenResult> RequestAccessToken(AccessTokenRequestOptions options)
throw new NotImplementedException();
JSRuntime.cs
using Microsoft.JSInterop;
using System.Threading;
using System.Threading.Tasks;
namespace Aguacongas.TheIdServer.Services
public class JSRuntime : IJSRuntime
public ValueTask<TValue> InvokeAsync<TValue>(string identifier, object[] args)
return new ValueTask<TValue>();
public ValueTask<TValue> InvokeAsync<TValue>(string identifier, CancellationToken cancellationToken, object[] args)
return new ValueTask<TValue>();
我也删除了:
builder.RootComponents.Add<App>("app");
来自 blazor 应用的 Program.cs
【讨论】:
非常感谢您帮助我前进!【参考方案2】:所以答案是将services.AddApiAuthorization();
添加到服务器Startup.cs
这解决了缺少服务注册的问题,但是之后还有一个错误。从目前的情况来看,身份验证不支持预渲染。
处理请求时发生未处理的异常。 InvalidOperationException:在服务器端预呈现期间无法发出 javascript 互操作调用,因为该页面尚未加载到浏览器中。预渲染组件必须将任何 JavaScript 互操作调用包装在条件逻辑中,以确保在预渲染期间不会尝试这些互操作调用。 Microsoft.AspNetCore.Mvc.ViewFeatures.UnsupportedJavaScriptRuntime.Microsoft.JSInterop.IJSRuntime.InvokeAsync(string identifier, object[] args)
【讨论】:
以上是关于未注册身份验证 AuthenticationStateProvider 的 Blazor Wasm 托管预渲染的主要内容,如果未能解决你的问题,请参考以下文章