Blazor Server应用如何基于用户名实现页面授权管控
Blazor Server Windows认证下基于用户名的授权实现方案
核心逻辑:Windows身份验证仍由IIS/系统层完成,只在应用授权层增加用户名白名单校验,不在列表内的已认证用户直接被撤销所有页面访问权限,全程不依赖角色体系。
1. 配置用户名白名单
在appsettings.json中维护允许访问的用户名列表,注意Windows认证返回的用户名带域/机器名前缀,必须写完整格式:
{ "AllowedUserSettings": { "WhiteList": [ "COMPANY-DOMAIN\\zhang.san", "COMPANY-DOMAIN\\li.si", "LOCAL-MACHINE\\dev-account", "IIS APPPOOL\\BlazorAppProd" // 必须加入IIS应用池对应的内置账号,避免部署后权限异常 ] } }
如果开启了配置热更新,后续增删白名单用户不需要重启应用即可生效。
2. 实现自定义用户名授权逻辑
不需要引入第三方权限库,写两个基础类完成校验:
首先定义授权要求:
// UsernameRequirement.cs using Microsoft.AspNetCore.Authorization; public class UsernameWhitelistRequirement : IAuthorizationRequirement { public IReadOnlyList<string> AllowedUsernames { get; } public UsernameWhitelistRequirement(List<string> allowedUsernames) { AllowedUsernames = allowedUsernames.AsReadOnly(); } }
然后实现对应的授权处理器:
// UsernameWhitelistHandler.cs using Microsoft.AspNetCore.Authorization; public class UsernameWhitelistHandler : AuthorizationHandler<UsernameWhitelistRequirement> { protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, UsernameWhitelistRequirement requirement) { var currentUser = context.User.Identity; // 未认证直接失败 if (currentUser == null || !currentUser.IsAuthenticated || string.IsNullOrWhiteSpace(currentUser.Name)) { context.Fail(); return Task.CompletedTask; } // 忽略大小写匹配白名单,Windows用户名本身大小写不敏感 if (requirement.AllowedUsernames.Contains(currentUser.Name, StringComparer.OrdinalIgnoreCase)) { context.Succeed(requirement); } else { // 不在白名单直接拒绝,不进入后续其他授权校验 context.Fail(); } return Task.CompletedTask; } }
3. 注册服务配置全局授权策略
在Program.cs中注册服务,把白名单校验配置为全局默认策略,所有页面默认都会走校验:
var builder = WebApplication.CreateBuilder(args); // 读取白名单配置 var whiteList = builder.Configuration .GetSection("AllowedUserSettings:WhiteList") .Get<List<string>>() ?? new List<string>(); // 注册自定义授权处理器 builder.Services.AddScoped<IAuthorizationHandler, UsernameWhitelistHandler>(); // 配置授权策略 builder.Services.AddAuthorization(options => { // 全局默认策略:必须通过Windows认证 + 必须在白名单内 options.DefaultPolicy = new AuthorizationPolicyBuilder() .AddRequirements(new UsernameWhitelistRequirement(whiteList)) .RequireAuthenticatedUser() .Build(); // 额外注册命名策略,供个别页面单独指定使用 options.AddPolicy("WhitelistOnly", policy => { policy.AddRequirements(new UsernameWhitelistRequirement(whiteList)); policy.RequireAuthenticatedUser(); }); }); // 后续按原有逻辑注册Razor组件、Blazor Server服务即可
部署注意:IIS站点必须开启Windows身份验证、关闭匿名身份验证,否则无法拿到正确的Windows用户名。
4. 页面级访问控制
全局策略默认对所有带路由的Razor组件生效,不需要额外加特性。如果需要单独配置特殊页面:
- 对需要额外强调权限的页面,在顶部加特性明确标注:
@attribute [Authorize(Policy = "WhitelistOnly")] - 对需要放开权限的页面(比如无权限提示页、健康检查页),加匿名访问特性:
@attribute [AllowAnonymous]
在App.razor中配置无权限时的展示内容,不需要额外写跳转逻辑:
<Router AppAssembly="@typeof(App).Assembly"> <Found Context="routeData"> <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"> <NotAuthorized> <div class="alert alert-danger mt-5 text-center"> <h3>访问被拒绝</h3> <p>您的账号不在系统允许访问的用户列表内,请联系管理员开通权限。</p> </div> </NotAuthorized> </AuthorizeRouteView> </Found> <NotFound> <LayoutView Layout="@typeof(MainLayout)"> <p class="mt-5 text-center">抱歉,您访问的页面不存在。</p> </LayoutView> </NotFound> </Router>
常见踩坑说明
- 不要只写用户名不带域/机器前缀,比如Windows返回的用户名是
DOMAIN\zhangsan,白名单只写zhangsan会100%匹配失败 - 不要用大小写敏感的字符串匹配,Windows系统对用户名大小写不敏感,避免因为账号名大小写格式问题误拦截合法用户
- 撤销用户权限只需要把对应用户名从白名单移除即可,不需要修改角色映射、用户状态等其他配置
内容的提问来源于stack exchange,提问作者codewise
相关产品推荐
相关产品推荐

