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

ASP.NET Core Razor Pages中AddNegotiate角色授权失效问题

问题

ASP.NET Core Razor Pages应用通过.AddNegotiate()实现Windows认证,利用ClaimsTransformer根据AD组分配角色(如"Admin"),并配置了"SiteAuth"授权策略。当前遇到以下异常情况:

  • 使用[Authorize(Policy = "SiteAuth")]对Razor页面授权正常
  • 使用[Authorize(Roles = "Admin")]授权失效,会重定向到未授权页面
  • 仅使用[Authorize]可正常授权
  • if (User.HasClaim(claim => claim.Value == "Admin"))判断能正常生效

断点调试确认ClaimsTransformer已执行,角色Claim已添加,调试输出的Claims中也包含"Admin"角色,且无拼写错误。

原因分析

问题核心在于WindowsIdentity的特殊性:当使用[Authorize(Roles = "...")]时,授权系统会调用User.IsInRole()方法,而WindowsIdentity的IsInRole()是直接与AD交互验证用户所属组,不会读取我们通过ClaimsTransformer添加的Role Claim。即使Claims集合中存在对应的Role声明,IsInRole()仍会返回false,导致授权失效。

而User.HasClaim()和自定义策略SiteAuth直接检查Claims集合,因此可以正常生效;仅[Authorize]只验证用户是否已认证,也不受影响。

解决方案

在ClaimsTransformer中,不要直接修改原有的WindowsIdentity,而是创建一个新的ClaimsIdentity,复制原身份的所有声明,再添加自定义角色声明,最后将新身份添加到ClaimsPrincipal中。这样授权系统会使用新身份的IsInRole()方法,该方法会读取Claims集合中的Role声明。

修改后的ClaimsTransformer代码如下:

public class ClaimsTransformer : IClaimsTransformation
{
    private readonly SiteSettings _siteSettings;
    private readonly ILogger<ClaimsTransformer> _logger;

    public ClaimsTransformer(SiteSettings siteSettings, ILogger<ClaimsTransformer> logger)
    {
        _siteSettings = siteSettings;
        _logger = logger;
    }
    
    public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
    {
        // 避免重复添加自定义身份
        if (principal.Identities.Any(id => id.AuthenticationType == "CustomRoleIdentity"))
        {
            return Task.FromResult(principal);
        }

        var wi = (WindowsIdentity)principal.Identity;
        var groups = wi.Groups;

        // 创建新的ClaimsIdentity,复制原有声明并指定角色声明类型
        var customIdentity = new ClaimsIdentity(
            principal.Identity.Claims,
            "CustomRoleIdentity",
            principal.Identity.NameClaimType,
            ClaimTypes.Role
        );

        if (groups != null)
        {
            foreach (var group in groups)
            {
                try
                {
                    string groupName = string.Empty;
                    var ntAccount = group.Translate(typeof(NTAccount)).ToString();
                    if(_siteSettings.AdminGroups.TryGetValue(ntAccount, out groupName))
                    {
                        if(!customIdentity.HasClaim(c => c.Value == groupName))
                        {
                            _logger.LogInformation($"Adding role {groupName} to claims.");
                            var claim = new Claim(ClaimTypes.Role, groupName);
                            customIdentity.AddClaim(claim);
                        }
                    }                    
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "Error processing AD group");
                    throw;
                }
            }
        }

        // 将新身份添加到Principal中
        var newPrincipal = new ClaimsPrincipal(customIdentity);
        return Task.FromResult(newPrincipal);
    }    
}

若希望保留原WindowsIdentity,也可选择将新身份附加到原Principal:

// 保留原身份,添加新身份
var newPrincipal = new ClaimsPrincipal(principal);
newPrincipal.AddIdentity(customIdentity);
return Task.FromResult(newPrincipal);
验证方式

修改完成后可通过以下方式确认修复效果:

  • 在页面中调用User.IsInRole("Admin"),应返回true
  • 使用[Authorize(Roles = "Admin")]标记页面,授权可正常通过
  • 访问/debug-claims接口,可看到新身份中的Role声明

内容的提问来源于stack exchange,提问作者Jon P

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 19:39:51