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

ASP.NET Core授权:如何实现OR组合权限需求?

在ASP.NET Core中用Claims实现层级化「或」权限需求

刚好我之前做过类似的需求,用Claims来实现这种层级化的「或」权限其实比传统角色方案更灵活,下面给你两种实用的实现思路,一步步来落地:

方案一:自定义授权策略(快速上手)

首先先确认你的AccountType枚举定义:

public enum AccountType
{
    User,
    BiggerUser,
    BiggestUser
}

接下来在Program.cs(.NET 6+)或者Startup.cs中配置授权策略,核心思路是通过RequireAssertion编写自定义判断逻辑,实现「用户级别≥目标级别即可访问」的规则:

builder.Services.AddAuthorization(options =>
{
    // 定义需要BiggerUser及以上权限的策略
    options.AddPolicy("RequireBiggerUserOrHigher", policy =>
        policy.RequireAssertion(context =>
        {
            // 从用户Claims中获取AccountType(注意这里的ClaimType要和你登录时添加的一致)
            var accountTypeClaim = context.User.FindFirst("AccountType");
            if (accountTypeClaim == null)
                return false;
            
            // 解析枚举值
            if (!Enum.TryParse<AccountType>(accountTypeClaim.Value, out var userAccountType))
                return false;
            
            // 核心逻辑:层级高的用户自动拥有低级别权限
            return userAccountType >= AccountType.BiggerUser;
        }));

    // 同理,定义最低要求为User的策略(所有用户都能访问)
    options.AddPolicy("RequireUserOrHigher", policy =>
        policy.RequireAssertion(context =>
        {
            var accountTypeClaim = context.User.FindFirst("AccountType");
            if (accountTypeClaim == null)
                return false;
            
            return Enum.TryParse<AccountType>(accountTypeClaim.Value, out var userAccountType) 
                && userAccountType >= AccountType.User;
        }));
});

配置完成后,直接在控制器/Action上使用[Authorize]特性指定策略即可:

// 只有BiggerUser和BiggestUser能访问
[Authorize(Policy = "RequireBiggerUserOrHigher")]
public IActionResult ManageSettings()
{
    return View();
}

// 所有三种类型用户都能访问
[Authorize(Policy = "RequireUserOrHigher")]
public IActionResult PublicHome()
{
    return View();
}

方案二:自定义授权属性(更优雅的写法)

如果觉得每次写策略名称麻烦,可以封装一个自定义的[AuthorizeAccountType]特性,让代码更直观:

1. 定义授权要求和处理器

// 自定义授权属性
public class AuthorizeAccountTypeAttribute : AuthorizeAttribute
{
    public AuthorizeAccountTypeAttribute(AccountType minimumRequiredType)
    {
        Policy = $"RequireAccountType_{minimumRequiredType}";
    }
}

// 授权要求模型(传递最低权限级别)
public class AccountTypeRequirement : IAuthorizationRequirement
{
    public AccountType MinimumRequiredType { get; }

    public AccountTypeRequirement(AccountType minimumRequiredType)
    {
        MinimumRequiredType = minimumRequiredType;
    }
}

// 授权逻辑处理器
public class AccountTypeAuthorizationHandler : AuthorizationHandler<AccountTypeRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, AccountTypeRequirement requirement)
    {
        // 获取用户的AccountType Claim
        var accountTypeClaim = context.User.FindFirst("AccountType");
        if (accountTypeClaim == null)
        {
            context.Fail();
            return Task.CompletedTask;
        }

        // 解析枚举值
        if (!Enum.TryParse<AccountType>(accountTypeClaim.Value, out var userAccountType))
        {
            context.Fail();
            return Task.CompletedTask;
        }

        // 判断是否满足权限要求
        if (userAccountType >= requirement.MinimumRequiredType)
        {
            context.Succeed(requirement);
        }
        else
        {
            context.Fail();
        }

        return Task.CompletedTask;
    }
}

2. 注册服务和策略

在Program.cs中注册处理器,并自动为每个枚举级别生成策略:

// 注册授权处理器
builder.Services.AddScoped<IAuthorizationHandler, AccountTypeAuthorizationHandler>();

builder.Services.AddAuthorization(options =>
{
    // 遍历所有AccountType,自动生成对应策略
    foreach (AccountType type in Enum.GetValues(typeof(AccountType)))
    {
        options.AddPolicy($"RequireAccountType_{type}", policy =>
            policy.AddRequirements(new AccountTypeRequirement(type)));
    }
});

3. 使用自定义属性

现在可以直接在控制器/Action上用直观的方式指定权限:

// 要求BiggerUser及以上权限
[AuthorizeAccountType(AccountType.BiggerUser)]
public IActionResult ManageUsers()
{
    return View();
}

// 只允许BiggestUser访问
[AuthorizeAccountType(AccountType.BiggestUser)]
public IActionResult SystemAdmin()
{
    return View();
}

关键补充:登录时添加AccountType Claim

不管用哪种方案,都需要在用户登录时把AccountType作为Claim添加到用户身份中,比如:

// 假设登录时从数据库获取到用户的AccountType是BiggestUser
var userClaims = new List<Claim>
{
    new Claim(ClaimTypes.Name, "username"),
    new Claim("AccountType", AccountType.BiggestUser.ToString())
};

var claimsIdentity = new ClaimsIdentity(userClaims, CookieAuthenticationDefaults.AuthenticationScheme);
await HttpContext.SignInAsync(
    CookieAuthenticationDefaults.AuthenticationScheme,
    new ClaimsPrincipal(claimsIdentity));

这种基于Claims的方案的好处是:你可以轻松扩展AccountType枚举,或者添加其他自定义Claim来组合权限,比传统角色系统更灵活,也更符合ASP.NET Core授权系统的设计理念。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 12:11:28