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

Razor Pages中AddAuthorization实现HR部门授权策略失败排查

问题诊断与解决方案

你的核心问题在于重复创建认证会话,且自定义声明所在的会话未被授权中间件读取,具体分析和修复方案如下:

问题根源

你在登录逻辑中先调用了_signInManager.PasswordSignInAsync(使用Identity默认的Identity.Application认证Scheme创建会话),随后又手动调用HttpContext.SignInAsync("MyCookieAuth", claimsPrincipal)创建了另一个独立的认证会话。而ASP.NET Core的授权中间件默认只会读取默认认证Scheme对应的Claims,因此你手动添加的Department声明并没有被授权策略识别到。

修复方案

方案1:直接使用自定义认证会话(无需Identity用户系统额外功能)

移除SignInManager的登录调用,自行完成用户名密码验证后,直接创建包含自定义声明的认证会话:

修改Login页面的OnPostAsync方法:

public async Task<IActionResult> OnPostAsync(User user)
{
    // 自行实现用户名密码验证逻辑(比如从数据库校验)
    bool isValidCredentials = /* 替换为你的验证逻辑,例如检查用户名密码是否匹配 */;
    
    if (isValidCredentials)
    {
        _logger.LogInformation("User logged in.");
        
        var claims = new List<Claim> {
            new Claim(ClaimTypes.Name, "admin"),
            new Claim(ClaimTypes.Email, "admin@mywebsite.com"),
            new Claim("Department", "HR")
        };
        
        var identity = new ClaimsIdentity(claims, "MyCookieAuth");
        ClaimsPrincipal claimsPrincipal = new ClaimsPrincipal(identity);
        
        await HttpContext.SignInAsync("MyCookieAuth", claimsPrincipal);
        return RedirectToPage("contact");
    }
    else
    {
        return Page();
    }
}

同时在Program.cs中添加对应Cookie认证的配置(确保在授权配置之前):

// 配置Cookie认证
builder.Services.AddAuthentication("MyCookieAuth")
    .AddCookie("MyCookieAuth", options =>
    {
        options.LoginPath = "/Login"; // 指定登录页面路径
    });

// 原有的授权和Razor Pages配置保持不变
builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("MustBelongToHRDepartment",
            policy => policy.RequireClaim("Department", "HR"));
});

builder.Services.AddRazorPages(options =>
{
    options.Conventions.AuthorizePage("/contact", "MustBelongToHRDepartment");
});

方案2:将自定义声明添加到Identity用户体系(需保留Identity功能)

如果需要继续使用Identity的用户管理功能,不要手动创建新的认证会话,而是将自定义声明添加到已登录的用户身份中:

修改Login页面的OnPostAsync方法:

public async Task<IActionResult> OnPostAsync(User user)
{
    var result = await _signInManager.PasswordSignInAsync(user.username,
                   user.password, user.rememberMe, lockoutOnFailure: true);
                   
    if (result.Succeeded)
    {
        _logger.LogInformation("User logged in.");
        
        // 获取当前登录的用户实体
        var currentUser = await _userManager.FindByNameAsync(user.username);
        if (currentUser != null)
        {
            // 检查用户是否已存在该声明,避免重复添加
            var existingClaim = await _userManager.GetClaimsAsync(currentUser)
                .FirstOrDefault(c => c.Type == "Department" && c.Value == "HR");
                
            if (existingClaim == null)
            {
                await _userManager.AddClaimAsync(currentUser, new Claim("Department", "HR"));
            }
            
            // 刷新登录会话,使新声明生效
            await _signInManager.RefreshSignInAsync(currentUser);
        }
        
        return RedirectToPage("contact");
    }
    else
    {
        return Page();
    }
}

关键注意事项

确保在Program.cs的中间件管道中,认证中间件在授权中间件之前注册:

var app = builder.Build();

// ...其他中间件(如静态文件、路由等)

app.UseAuthentication(); // 必须在UseAuthorization之前
app.UseAuthorization();

app.MapRazorPages();

app.Run();

内容的提问来源于stack exchange,提问作者Kaden Gaines

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 12:55:19