Blazor 8 Server模式下Windows Authentication的NotAuthorized不显示问题
1. 补全Windows认证服务配置
你的Program.cs里只注册了Authentication方案,但没完成Negotiate认证的完整配置,还漏了启用授权中间件。修改后的Program.cs如下:
using BlazorApp11.Components; using Microsoft.AspNetCore.Authentication.Negotiate; namespace BlazorApp11 { public class Program { public static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); builder.Services.AddRazorComponents() .AddInteractiveServerComponents(); // 补全Negotiate认证配置 builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme) .AddNegotiate(); builder.Services.AddAuthorization(options => { options.FallbackPolicy = options.DefaultPolicy; }); builder.Services.AddCascadingAuthenticationState(); // 添加上Blazor Server必需的身份状态提供者 builder.Services.AddScoped<AuthenticationStateProvider, ServerAuthenticationStateProvider>(); var app = builder.Build(); if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseAntiforgery(); // 必须启用认证和授权中间件,顺序不能乱 app.UseAuthentication(); app.UseAuthorization(); app.MapRazorComponents<App>() .AddInteractiveServerRenderMode(); app.Run(); } } }
2. 解决服务器提前返回403的问题
默认情况下,当用户不符合页面上[Authorize(Roles = "test")]的要求时,ASP.NET Core的授权中间件会直接返回403,根本不会进入Blazor的组件渲染流程,所以NotAuthorized内容肯定显示不出来。有两种解决方式:
方式一:改用组件内的AuthorizeView
把Weather.razor里的@attribute [Authorize(Roles = "test")]删掉,用AuthorizeView把页面内容包起来:
@page "/weather" @using Microsoft.AspNetCore.Authorization @attribute [StreamRendering] <PageTitle>Weather</PageTitle> <AuthorizeView Roles="test"> <Authorized> <h1>Weather</h1> <p>This component demonstrates showing data.</p> @if (forecasts == null) { <p><em>Loading...</em></p> } else { <table class="table"> <thead> <tr> <th>Date</th> <th>Temp. (C)</th> <th>Temp. (F)</th> <th>Summary</th> </tr> </thead> <tbody> @foreach (var forecast in forecasts) { <tr> <td>@forecast.Date.ToShortDateString()</td> <td>@forecast.TemperatureC</td> <td>@forecast.TemperatureF</td> <td>@forecast.Summary</td> </tr> } </tbody> </table> } </Authorized> <NotAuthorized> <h1>Not Authorized</h1> <p>你没有访问该页面的权限</p> </NotAuthorized> </AuthorizeView> @code { // 原有的代码保持不变 }
方式二:自定义授权策略,让Blazor接管未授权显示
要是非得用页面级的[Authorize]属性,就得改授权配置,不让服务器直接返回403:
在Program.cs的AddAuthorization里加自定义策略:
builder.Services.AddAuthorization(options => { options.FallbackPolicy = options.DefaultPolicy; // 自定义Blazor专用的授权策略 options.AddPolicy("BlazorAuthorize", policy => { policy.RequireRole("test"); policy.AuthenticationSchemes.Add(NegotiateDefaults.AuthenticationScheme); }); });
然后Weather.razor里改成@attribute [Authorize(Policy = "BlazorAuthorize")],同时记得把Routes.razor里的拼写错误改了——Not Authroized少了个字母,应该是Not Authorized。
3. 修正Routes.razor的拼写错误
Routes.razor里的未授权文本拼错了,改过来才能显示正确内容:
@using Microsoft.AspNetCore.Components.Authorization <Router AppAssembly="@typeof(Program).Assembly"> <Found Context="routeData"> <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(Layout.MainLayout)"> <NotAuthorized> Not Authorized </NotAuthorized> </AuthorizeRouteView> <FocusOnNavigate RouteData="@routeData" Selector="h1" /> </Found> </Router>
核心原因总结
Blazor Server里页面级的[Authorize]会触发服务器端的授权检查,没通过直接就返回403了,根本到不了Blazor组件渲染那一步。所以要么用组件内的AuthorizeView来处理授权逻辑,要么调整授权策略让Blazor来处理未授权的显示。另外必须确保认证和授权中间件在请求管道里正确注册,顺序不能搞反。
内容的提问来源于stack exchange,提问作者chobo2

