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

如何不依赖庞大的Microsoft.Identity.Web包实现RequiredScope属性功能?

自定义实现.NET 8 API的范围授权(替代Microsoft.Identity.Web的RequiredScopeAttribute)

你完全可以自己实现轻量的范围授权逻辑,不需要引入Microsoft.Identity.Web的冗余依赖。以下是针对第三方IDP(如Amazon Cognito、Okta)的实现方案:

1. 定义Scope授权需求与处理程序

首先创建授权需求类承载需要验证的scope列表,再实现对应的授权处理逻辑:

自定义Scope授权需求

public class ScopeRequirement : IAuthorizationRequirement
{
    public string[] RequiredScopes { get; }

    public ScopeRequirement(params string[] requiredScopes)
    {
        RequiredScopes = requiredScopes ?? throw new ArgumentNullException(nameof(requiredScopes));
    }
}

实现授权处理逻辑

这个类负责从用户的Claims中提取scope并验证是否符合要求:

public class ScopeAuthorizationHandler : AuthorizationHandler<ScopeRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, ScopeRequirement requirement)
    {
        // 从Claims中获取scope声明,适配Cognito/Okta等常见IDP的声明类型
        var scopeClaim = context.User.FindFirst(ClaimTypes.Scope) 
                         ?? context.User.FindFirst("scope");
        
        if (scopeClaim == null)
            return Task.CompletedTask;

        var userScopes = scopeClaim.Value.Split(' ', StringSplitOptions.RemoveEmptyEntries);
        
        // 验证用户是否拥有所有必需的scope(可改为Any实现"或"逻辑)
        var meetsRequirement = requirement.RequiredScopes
            .All(requiredScope => userScopes.Contains(requiredScope, StringComparer.OrdinalIgnoreCase));

        if (meetsRequirement)
            context.Succeed(requirement);

        return Task.CompletedTask;
    }
}

2. 创建标记属性(替代RequiredScopeAttribute)

写一个继承自AuthorizeAttribute的特性,用来在控制器/方法上标记需要的scope:

public class RequiredScopeAttribute : AuthorizeAttribute
{
    public RequiredScopeAttribute(params string[] scopes)
    {
        // 生成唯一策略名称,用于动态创建授权规则
        Policy = $"ScopePolicy_{string.Join("_", scopes)}";
    }
}

3. 注册授权服务与动态策略提供器

为避免手动注册每个scope组合的策略,实现动态策略提供器自动生成对应规则:

动态策略提供器

public class DynamicScopePolicyProvider : DefaultAuthorizationPolicyProvider
{
    private readonly AuthorizationOptions _options;

    public DynamicScopePolicyProvider(IOptions<AuthorizationOptions> options) : base(options)
    {
        _options = options.Value;
    }

    public override async Task<AuthorizationPolicy?> GetPolicyAsync(string policyName)
    {
        // 识别Scope策略前缀,动态生成授权规则
        if (policyName.StartsWith("ScopePolicy_", StringComparison.OrdinalIgnoreCase))
        {
            var scopeNames = policyName["ScopePolicy_".Length..].Split('_', StringSplitOptions.RemoveEmptyEntries);
            var policyBuilder = new AuthorizationPolicyBuilder();
            policyBuilder.Requirements.Add(new ScopeRequirement(scopeNames));
            return policyBuilder.Build();
        }

        // 非Scope策略使用默认逻辑
        return await base.GetPolicyAsync(policyName);
    }
}

在Program.cs中注册服务

var builder = WebApplication.CreateBuilder(args);

// 添加授权服务
builder.Services.AddAuthorization();

// 注册动态策略提供器和Scope授权处理程序
builder.Services.AddSingleton<IAuthorizationPolicyProvider, DynamicScopePolicyProvider>();
builder.Services.AddScoped<IAuthorizationHandler, ScopeAuthorizationHandler>();

// 其他服务注册
builder.Services.AddControllers();

var app = builder.Build();

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

app.MapControllers();

app.Run();

4. 在API中使用

直接在控制器或方法上标记[RequiredScope]属性即可:

[ApiController]
[Route("api/orders")]
public class OrdersController : ControllerBase
{
    // 需要"orders:read"权限才能访问
    [HttpGet]
    [RequiredScope("orders:read")]
    public IActionResult GetOrders()
    {
        return Ok(new List<object>());
    }

    // 需要同时拥有"orders:read"和"orders:write"权限
    [HttpPut("{id}")]
    [RequiredScope("orders:read", "orders:write")]
    public IActionResult UpdateOrder(int id, [FromBody] object order)
    {
        return Ok("Order updated");
    }
}

适配不同IDP的注意事项

  • 部分IDP可能使用不同的scope声明类型,可在ScopeAuthorizationHandler中增加对应类型的检查。
  • 若需支持通配符(如orders:*),可修改验证逻辑为StartsWith或正则匹配。
  • 要实现"用户拥有任意一个必需scope即可访问",只需把处理程序中的All改为Any。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 12:33:23