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

ASP.NET Core Identity:如何直接基于Claims而非Policy实现授权

实现直接通过Claim检查的自定义授权方案

这个需求我之前也碰到过,完全不用写几百个重复的Policy,我们可以利用ASP.NET Core授权系统的**需求(Requirement)+处理器(Handler)**机制,配合自定义的Authorize属性来实现你要的[Authorize(Claim = "Key1")]效果,具体步骤如下:


1. 定义自定义授权需求

首先创建一个需求类,用来传递我们要检查的Claim类型:

public class ClaimExistsRequirement : IAuthorizationRequirement
{
    // 要检查的Claim类型(也就是你的密钥名称)
    public string ClaimType { get; }

    public ClaimExistsRequirement(string claimType)
    {
        ClaimType = claimType ?? throw new ArgumentNullException(nameof(claimType));
    }
}

2. 实现授权处理器

接下来写一个处理器类,负责检查当前用户是否拥有指定的Claim:

public class ClaimExistsHandler : AuthorizationHandler<ClaimExistsRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, ClaimExistsRequirement requirement)
    {
        // 检查用户是否包含目标Claim
        if (context.User.HasClaim(claim => claim.Type == requirement.ClaimType))
        {
            // 验证通过,标记需求已满足
            context.Succeed(requirement);
        }
        // 如果验证不通过,不需要主动调用Fail(),授权系统会自动返回未授权
        return Task.CompletedTask;
    }
}

3. 创建自定义Authorize属性

现在我们要做一个可以直接在Controller/Action上标记的属性,让它把需求传递给授权系统:

public class AuthorizeClaimAttribute : AuthorizeAttribute, IAuthorizationData
{
    // 暴露一个ClaimType属性,用来指定要检查的密钥名称
    public string ClaimType { get; set; }

    public IEnumerable<IAuthorizationRequirement> GetRequirements()
    {
        if (string.IsNullOrEmpty(ClaimType))
        {
            throw new InvalidOperationException("必须为AuthorizeClaimAttribute指定ClaimType!");
        }
        // 返回我们定义的需求
        yield return new ClaimExistsRequirement(ClaimType);
    }
}

4. 注册授权服务

在你的Program.cs(.NET 6+)或者Startup.cs中,注册我们的处理器:

// .NET 6+ Program.cs示例
var builder = WebApplication.CreateBuilder(args);

// 添加MVC服务(如果用的是API就加AddControllers)
builder.Services.AddControllersWithViews();

// 配置授权系统,并注册自定义处理器
builder.Services.AddAuthorization()
                .AddScoped<IAuthorizationHandler, ClaimExistsHandler>();

var app = builder.Build();

// ...其他中间件配置
app.UseAuthorization();

app.MapControllers();
app.Run();

5. 在Controller中使用

现在你就可以像你想要的那样,直接在Controller或Action上标记检查指定的Claim了:

public class SecretController : Controller
{
    // 检查用户是否拥有Key1这个密钥对应的Claim
    [AuthorizeClaim("Key1")]
    public IActionResult AccessWithKey1()
    {
        return View();
    }

    // 同时检查多个Claim(默认是逻辑与,用户需要同时拥有这两个Claim才能访问)
    [AuthorizeClaim("Key1"), AuthorizeClaim("Key2")]
    public IActionResult AccessWithBothKeys()
    {
        return View();
    }
}

额外说明

  • 如果需要逻辑或的检查(比如用户拥有Key1或Key2就能访问),可以稍微修改处理器,或者创建一个支持多Claim的需求类,不过你的场景里单个检查应该足够了。
  • 确保你的用户ClaimsPrincipal中已经正确添加了对应的密钥Claim(比如登录时从数据库读取用户的密钥列表,添加到Claims里)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 11:57:40