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

.NET Core 2.2 WebAPI:如何通过授权过滤控制器返回的集合子集?

刚好做过类似的场景,给你一步步拆解怎么实现这个需求——在.NET Core 2.2 WebAPI里,我们可以通过自定义授权逻辑把用户的权限转化为查询过滤器,确保控制器只返回用户有权限查看的Bar子集。

具体实现步骤

1. 定义自定义授权需求类

首先创建一个授权需求类,用来承载后续要传递的权限过滤信息:

public class BarAuthorizationRequirement : IAuthorizationRequirement
{
    // 存储用户允许访问的Bar ID集合,供控制器后续使用
    public List<int> AllowedBarIds { get; set; } = new List<int>();
}

2. 实现自定义AuthorizationHandler

接下来写核心的授权处理逻辑,从Bearer令牌的声明里解析出用户能访问的Bar ID,然后填充到需求类的集合中。这里假设你的令牌里有一个名为allowed_bar_ids的声明,值是逗号分隔的ID字符串(比如"1,2,3"):

public class BarAuthorizationHandler : AuthorizationHandler<BarAuthorizationRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, BarAuthorizationRequirement requirement)
    {
        // 从用户身份声明中获取权限信息
        var allowedIdsClaim = context.User.FindFirst("allowed_bar_ids");
        if (allowedIdsClaim == null)
        {
            // 没有权限声明,直接标记授权失败
            context.Fail();
            return Task.CompletedTask;
        }

        // 把声明值解析为整数ID集合
        var allowedIds = allowedIdsClaim.Value.Split(',')
            .Select(int.Parse)
            .ToList();
        
        // 将允许的ID集合存入需求对象,方便控制器获取
        requirement.AllowedBarIds = allowedIds;
        
        // 标记授权通过(我们的目标是获取过滤条件,而非直接拒绝请求)
        context.Succeed(requirement);
        return Task.CompletedTask;
    }
}

3. 在Startup中配置授权服务

在ConfigureServices方法里注册身份验证和自定义授权逻辑:

public void ConfigureServices(IServiceCollection services)
{
    // 配置Bearer令牌验证
    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidateLifetime = true,
                ValidateIssuerSigningKey = true,
                ValidIssuer = "你的Issuer",
                ValidAudience = "你的Audience",
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("你的签名密钥"))
            };
        });

    // 添加自定义授权策略
    services.AddAuthorization(options =>
    {
        options.AddPolicy("BarAccessPolicy", policy =>
            policy.Requirements.Add(new BarAuthorizationRequirement()));
    });
    
    // 注册自定义授权Handler到DI容器
    services.AddScoped<IAuthorizationHandler, BarAuthorizationHandler>();

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

4. 在Foo控制器中应用过滤条件

最后在控制器里,通过IAuthorizationService触发授权流程,拿到允许的Bar ID集合,再用这个集合过滤数据源:

[Route("foo")]
[ApiController]
public class FooController : ControllerBase
{
    private readonly IAuthorizationService _authorizationService;
    private readonly IBarRepository _barRepository; // 假设这是你的Bar数据访问服务

    public FooController(IAuthorizationService authorizationService, IBarRepository barRepository)
    {
        _authorizationService = authorizationService;
        _barRepository = barRepository;
    }

    [HttpGet("bars")]
    [Authorize(Policy = "BarAccessPolicy")]
    public async Task<IActionResult> GetBars()
    {
        var requirement = new BarAuthorizationRequirement();
        var authResult = await _authorizationService.AuthorizeAsync(User, requirement);
        
        if (!authResult.Succeeded)
        {
            return Forbid();
        }

        // 获取过滤用的Bar ID集合
        var allowedBarIds = requirement.AllowedBarIds;
        
        // 应用过滤器,只返回用户有权限查看的Bar
        var filteredBars = await _barRepository.GetBarsAsync(bar => allowedBarIds.Contains(bar.Id));
        
        return Ok(filteredBars);
    }
}

优化小技巧

如果你觉得在控制器里创建需求对象有点繁琐,可以改用HttpContext.Items来传递过滤条件:
在BarAuthorizationHandler的HandleRequirementAsync方法里,添加一行:

context.HttpContext.Items["AllowedBarIds"] = allowedIds;

然后在控制器里直接获取:

var allowedBarIds = HttpContext.Items["AllowedBarIds"] as List<int>;

这样代码会更简洁。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:01:17