You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core 6 Razor Pages中基于角色的Windows身份验证授权实现方案

ASP.NET Core 6 Razor Pages 实现Windows Authentication+自定义角色授权方案

针对你的需求,以下是适配ASP.NET Core 6 Razor Pages的完整实现步骤,完全满足Windows登录后注入自定义角色、支持User.IsInRole()和[Authorize(Roles)]特性的要求:

1. 启用Windows Authentication

在Program.cs中配置Windows认证(.NET 6使用Negotiate方案替代旧版WindowsAuth):

var builder = WebApplication.CreateBuilder(args);

// 添加Razor Pages服务
builder.Services.AddRazorPages();

// 配置Windows认证(Negotiate自动处理Kerberos/NTLM)
builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
    .AddNegotiate();

// 全局授权策略:要求所有请求必须经过认证(可选,按需配置)
builder.Services.AddAuthorization(options =>
{
    options.FallbackPolicy = new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .Build();
});

var app = builder.Build();

// 中间件顺序严格遵循:认证在前,授权在后
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

// 必须先执行认证,再执行授权
app.UseAuthentication();
app.UseAuthorization();

app.MapRazorPages();

app.Run();

开发环境测试时,需在项目属性的调试选项卡中勾选「启用Windows身份验证」,同时取消「启用匿名身份验证」。

2. 注入自定义角色到用户Claims

Windows认证仅提供用户的基础身份信息(如域账号),需通过IClaimsTransformation扩展Claims,注入自定义角色:

步骤2.1:实现自定义Claims转换器

新建CustomClaimsTransformer.cs,负责从你的数据源(数据库/配置)查询用户角色并注入:

using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Caching.Memory;

public class CustomClaimsTransformer : IClaimsTransformation
{
    private readonly IMemoryCache _cache;
    private readonly IUserRoleService _userRoleService; // 自定义角色查询服务

    public CustomClaimsTransformer(IMemoryCache cache, IUserRoleService userRoleService)
    {
        _cache = cache;
        _userRoleService = userRoleService;
    }

    public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
    {
        // 仅处理Windows认证用户
        if (principal.Identity is not WindowsIdentity windowsIdentity)
        {
            return principal;
        }

        var userDomainAccount = windowsIdentity.Name; // 格式:DOMAIN\Username
        var cacheKey = $"UserRoles_{userDomainAccount}";

        // 优先从缓存获取角色,减少数据库查询
        if (!_cache.TryGetValue(cacheKey, out List<string> userRoles))
        {
            // 调用自定义服务查询用户所属角色
            userRoles = await _userRoleService.GetRolesForUserAsync(userDomainAccount);
            
            // 缓存角色1小时(可根据业务调整过期时间)
            var cacheOptions = new MemoryCacheEntryOptions()
                .SetSlidingExpiration(TimeSpan.FromHours(1));
            _cache.Set(cacheKey, userRoles, cacheOptions);
        }

        // 为用户添加角色Claims
        var claimsIdentity = new ClaimsIdentity(principal.Identity);
        foreach (var role in userRoles)
        {
            claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, role));
        }

        return new ClaimsPrincipal(claimsIdentity);
    }
}

步骤2.2:注册服务

在Program.cs中注册Claims转换器和自定义角色服务:

// 注册内存缓存(默认已注册,显式声明更清晰)
builder.Services.AddMemoryCache();

// 注册自定义角色查询服务(需自行实现IUserRoleService接口)
builder.Services.AddScoped<IUserRoleService, UserRoleService>();

// 注册Claims转换器
builder.Services.AddScoped<IClaimsTransformation, CustomClaimsTransformer>();

IUserRoleService是你需要自行实现的服务,核心逻辑是根据用户的域账号(如DOMAIN\Username)从数据库或其他存储中查询对应的角色列表。

3. Razor Pages中使用角色授权

3.1 控制页面/操作访问

在PageModel类上添加[Authorize(Roles)]特性,限制只有指定角色的用户能访问:

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.RazorPages;

// 仅允许"Manage User Accounts"角色访问该页面
[Authorize(Roles = "Manage User Accounts")]
public class UserManagementModel : PageModel
{
    public void OnGet()
    {
        // 业务逻辑
    }
}

支持多角色,用逗号分隔:[Authorize(Roles = "Manage User Accounts, View Reports")]

3.2 页面内权限判断

在Razor视图(.cshtml)中直接使用User.IsInRole()进行条件渲染:

@if (User.IsInRole("Manage User Accounts"))
{
    <div class="action-bar">
        <a asp-page="/UserManagement/Create">新建用户</a>
    </div>
}

也可以使用ASP.NET Core的授权Tag Helper简化代码:

<a asp-page="/UserManagement/Create" asp-authorize="Manage User Accounts">新建用户</a>

4. 关键注意事项

  • 中间件顺序:UseAuthentication()必须在UseAuthorization()之前执行,否则授权逻辑无法获取用户身份信息。
  • 角色缓存:使用内存缓存可以避免重复查询数据库,但如果用户角色发生变更,需要手动清理对应缓存项。
  • 域环境配置:如果部署在域环境中,确保服务器和客户端均加入域,Kerberos认证才能正常工作;工作组环境会自动降级为NTLM认证。

内容的提问来源于stack exchange,提问作者Robert Hames

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 13:27:03