安全与风控
在 Blazor Web App…
当需要给 Blazor Web App 添加认证/授权,或遇到交互组件中认证状态为 null、SignInManager 抛异常、静态 SSR 中 <NotAuthorized> 不渲染、HttpContext.User 为 null 等问题时使用。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 49/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 85/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
在 Blazor Web App 中按渲通用
解决思路
- 先阅读工作区根目录的 `AGENTS.md`,确认项目的交互模式(interactivity mode)和范围,再动手修改。
- 在 `Program.cs`(服务端项目)注册认证服务:`builder.Services.AddCascadingAuthenticationState();` 和 `builder.Services.AddAuthorization();`。
- 若使用 ASP.NET Core Identity,额外注册 Identity 服务:`AddAuthentication` 设置 `DefaultScheme = IdentityConstants.ApplicationScheme`、`DefaultSignInScheme = IdentityConstants.ExternalScheme` 并 `.AddIdentityCookies()`;再 `AddIdentityCore<ApplicationUser>().AddRoles<IdentityRole>().AddEntityFrameworkStores<ApplicationDbContext>().AddSignInManager().AddDefaultTokenProviders()`。
- 在 `App.razor` 中为 `HeadOutlet` 和 `Routes` 使用 `@rendermode="RenderModeForPage"`,并在 `@code` 中通过 `[CascadingParameter] HttpContext HttpContext` 与 `HttpContext.AcceptsInteractiveRouting()` 判断:可交互路由返回 `InteractiveServer`(替换为应用实际渲染模式),否则返回 `null`,使被排除的页面走静态渲染。
- 在 `Routes.razor`(或路由所在处)使用 `AuthorizeRouteView`,并在 `<NotAuthorized>` 中判断:若 `context.User.Identity?.IsAuthenticated != true` 则渲染 `<RedirectToLogin />`,否则显示未授权提示;同时保留 `FocusOnNavigate`。
- 用 `[Authorize]` 特性保护页面:`@attribute [Authorize]`,或带角色/策略 `@attribute [Authorize(Roles = "Admin")]`、`@attribute [Authorize(Policy = "RequireManager")]`。
- 用 `AuthorizeView` 做条件 UI:`<Authorized>` 显示欢迎信息,`<NotAuthorized>` 显示登录链接;角色/策略变体用 `<AuthorizeView Roles="Admin,Manager">`。
- 在代码中访问认证状态:声明 `[CascadingParameter] private Task<AuthenticationState>? AuthState`,在 `OnInitializedAsync` 中 `await AuthState` 并用 `state.User.IsInRole("Admin")` 判断。
- Identity 页面(登录、注册、管理)必须保持静态 SSR:`SignInManager` 和 `UserManager` 内部使用 `HttpContext`,在交互组件中会抛异常。
- 在全局交互应用中,为每个 Identity 页面加 `@attribute [ExcludeFromInteractiveRouting]`,强制整页导航(退出交互 circuit),使其通过静态 SSR 管线渲染并获得真实 `HttpContext`。
- `App.razor` 必须使用 `AcceptsInteractiveRouting()`(见前述步骤)对这些页面返回 `null`,否则框架仍会尝试交互式渲染它们。
- 在按页(per-page)交互的应用中,Identity 页面默认就是静态的(无 `@rendermode` 指令),无需 `[ExcludeFromInteractiveRouting]`。
- WebAssembly / Auto 模式下认证状态需序列化:服务端 `Program.cs` 调用 `builder.Services.AddAuthenticationStateSerialization();`,客户端 `.Client/Program.cs` 调用 `builder.Services.AddAuthenticationStateDeserialization();`,否则 WASM 接管预渲染后 `Task<AuthenticationState>` 会解析为匿名用户。
- `AddAuthenticationStateSerialization` 可传选项包含角色和声明数据:`options => options.SerializeAllClaims = true`。
- 牢记渲染模式 × 认证矩阵:静态 SSR 有 `HttpContext.User`、`SignInManager` 可用、认证状态来自服务端管线、用中间件重定向且 `<NotAuthorized>` 不渲染;Server 交互无 `HttpContext.User`、`SignInManager` 抛异常、认证状态来自 `CascadingAuthenticationState`、用 `[Authorize]` + `AuthorizeView`;WebAssembly 无 `HttpContext.User`、`SignInManager` 抛异常、认证状态由服务端序列化、需序列化/反序列化;Auto 在 WASM 后无 `HttpContext.User`、`SignInManager` 抛异常、认证状态由服务端序列化、需在**两个** `Program.cs` 中都注册。
- 避免常见错误:交互组件中不要用 `HttpContext.User`(会得到 null 或过期声明),改用 `[CascadingParameter] Task<AuthenticationState>`;不要在交互组件中用 `SignInManager`(会抛 `InvalidOperationException`),移到带 `[ExcludeFromInteractiveRouting]` 的静态 SSR 页面;不要漏掉 `AddAuthenticationStateSerialization`(否则 WASM 加载后变匿名用户),服务端加序列化、客户端加反序列化;静态 SSR 布局中 `<NotAuthorized>` 不会显示,应通过 `LoginPath` 或 `RedirectToLogin` 组件重定向;全局交互若没有 `AcceptsInteractiveRouting` 会导致 Identity 页面崩溃;漏掉 `AddCascadingAuthenticationState()` 会使 `Task<AuthenticationState>` 为 null。
适用边界 · 注意事项
- 不要用于一般组件编写(参见 author-component)。
- 不要用于与认证无关的预渲染问题(参见 support-prerendering)。
- 不要用于管理非认证的级联状态(参见 coordinate-components)。