首页 > 解决方案 > 根据路径过滤

问题描述

我正在制作一个基于各种 API 控制器的系统。使用适当的 jwt 令牌。(此令牌包含用户,以及他可以访问的客户)目前控制器需要按照惯例检查给定用户是否可以访问相关客户。

我想知道我是否可以更优雅地做到这一点:) - 假设基本 url 总是 /api/customer//,那么最好的解决方案是制作一个“东西”,总是检查是否是给定用户的一部分宣称。

标签: authorizationasp.net-core-webapi

解决方案


您可以在 ASP.NET Core中使用基于策略的授权。

为了满足您的要求,首先创建授权策略:

services.AddAuthorization(options =>
{
    options.AddPolicy("CustomRequire", policy =>
        policy.Requirements.Add(new CustomerRequirement()));
});

注册一项需求,创建CustomerRequirement.cs

public class CustomerRequirement : IAuthorizationRequirement
{
    public CustomerRequirement()
    {
    }
}

创建CustomerHandler.cs

public class CustomerHandler : AuthorizationHandler<CustomerRequirement>
{
    IHttpContextAccessor _httpContextAccessor = null;

    public CustomerHandler(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
                                                CustomerRequirement requirement)
    {

        HttpContext httpContext = _httpContextAccessor.HttpContext;


        var path = httpContext.Request.Path;

        //split the path to get the customer base on your path .

        var customerName = "customerFromPath";

        if (!context.User.HasClaim(c => c.Type == "customer"))
        {
            return Task.CompletedTask;
        }

        var customer = context.User.FindAll(c => c.Type == "customer" ).FirstOrDefault();

        if (customerName.Equals(customer.Value.ToString()))
        {
            context.Succeed(requirement);
        }

        //TODO: Use the following if targeting a version of
        //.NET Framework older than 4.6:
        //      return Task.FromResult(0);
        return Task.CompletedTask;
    }
}

要使用IHttpContextAccessor,您可能需要在 DI 设置中注册它,如下所示:

services.AddHttpContextAccessor();

在配置期间在服务集合中注册处理程序:

services.AddSingleton<IAuthorizationHandler, CustomerHandler>();

现在您可以将策略应用于 MVC 控制器:

[Authorize(Policy = "CustomRequire")]
// GET api/values/5
[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
    return "value";
}

当然,您也可以在您的应用程序中全局注册该策略。


推荐阅读