Blazor Web App(.NET 8)集成微软登录报错:类型转换失败
问题定位与解决方案
根源分析
你遇到的InvalidCastException是因为Blazor Web App(交互式服务器模式)中混用了WebAssembly专属的认证服务:
- 你注册了
AddRemoteAuthentication和AddApiAuthorization,这两个是为Blazor WebAssembly设计的服务,而你的项目是服务器端渲染模式,依赖的是ServerAuthenticationStateProvider,两者类型不兼容,导致转换失败。 SignOutSessionStateManager也是WebAssembly的组件,Blazor Server不需要它。
修复步骤
1. 移除WebAssembly相关的认证服务
从Main方法中删除以下代码:
builder.Services.AddApiAuthorization(); builder.Services.AddRemoteAuthentication<RemoteAuthenticationState, RemoteUserAccount, OidcProviderOptions>(); builder.Services.AddScoped<SignOutSessionStateManager>();
2. 简化认证服务配置
保留Blazor Server兼容的微软身份认证配置即可,修正后的Main方法核心代码如下:
public static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); // 基础组件服务 builder.Services.AddRazorComponents() .AddInteractiveServerComponents(); // AUTH - 仅保留Blazor Server兼容的配置 builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd")); builder.Services.AddControllersWithViews() .AddMicrosoftIdentityUI(); builder.Services.AddAuthorization(options => { options.FallbackPolicy = options.DefaultPolicy; }); builder.Services.AddServerSideBlazor() .AddMicrosoftIdentityConsentHandler(); builder.Services.AddRazorPages(); // 若自定义AuthStateProvider继承自ServerAuthenticationStateProvider,保留此注册 builder.Services.TryAddScoped<AuthenticationStateProvider, AuthStateProvider>(); // 单例服务 builder.Services.AddSingleton<DataService>(); builder.Services.AddSingleton<DataProcessor>(); var app = builder.Build(); // 请求管道配置 if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseAntiforgery(); // 中间件顺序调整:路由需在认证授权之前 app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.MapRazorPages(); app.MapControllers(); app.MapRazorComponents<App>() .AddInteractiveServerRenderMode(); app.Run(); }
3. 实现正确的注销功能
在Blazor组件中,可通过两种方式实现注销:
- 导航到微软身份内置注销端点:
@inject NavigationManager NavManager <button @onclick="SignOut">注销</button> @code { private void SignOut() { NavManager.NavigateTo("/MicrosoftIdentity/Account/SignOut", forceLoad: true); } }
- 注入
SignOutManager执行注销:
@inject SignOutManager<ClaimsPrincipal> SignOutManager <button @onclick="SignOutAsync">注销</button> @code { private async Task SignOutAsync() { await SignOutManager.SignOutAsync(); } }
关于预渲染
你禁用预渲染的方式是有效的,但这不是导致当前认证错误的原因,修复上述服务注册问题后,注销功能即可正常工作。
内容的提问来源于stack exchange,提问作者PokkeYuri
相关产品推荐
相关产品推荐

