一尘不染

如何在ASP.NET Core中创建自定义AuthorizeAttribute?

c#

我正在尝试在ASP.NET Core中创建自定义授权属性。在以前的版本中,可以覆盖bool AuthorizeCore(HttpContextBase httpContext)。但这不再存在于中AuthorizeAttribute

制作自定义AuthorizeAttribute的当前方法是什么?

我要完成的工作:我在标题授权中收到一个会话ID。通过该ID,我将知道特定操作是否有效。


阅读 1200

收藏
2020-05-19

共1个答案

一尘不染

ASP.Net Core团队推荐的方法是使用新的策略设计,在此将其详细记录。新方法背后的基本思想是使用新的[Authorize]属性来指定“策略”(例如[Authorize( Policy = "YouNeedToBe18ToDoThis")],该策略在应用程序的Startup.cs中注册的位置,以执行某些代码块(即,确保用户有年龄要求)年龄在18岁以上)。

策略设计是对框架的重要补充,ASP.Net Security
Core团队的引入值得赞扬。也就是说,它并不适合所有情况。这种方法的缺点在于,它无法为最简单的要求简单断言给定的控制器或操作需要给定的索赔类型的最常见需求提供方便的解决方案。如果应用程序可能具有数百个离散权限来管理单个REST资源(“
CanCreateOrder”,“ CanReadOrder”,“ CanUpdateOrder”,“
CanDeleteOrder”等)上的CRUD操作,则新方法要么需要重复的一对一操作,要么策略名称和声明名称之间的一种映射(例如,options.AddPolicy("CanUpdateOrder", policy => policy.RequireClaim(MyClaimTypes.Permission, "CanUpdateOrder));),或编写一些代码以在运行时执行这些注册(例如,从数据库中读取所有索赔类型并循环执行上述调用)。在大多数情况下,这种方法的问题是不必要的开销。

尽管ASP.Net Core Security团队建议不要创建自己的解决方案,但在某些情况下,这可能是最明智的选择。

以下是使用IAuthorizationFilter的实现,以提供一种简单的方式来表达给定控制器或操作的声明要求:

public class ClaimRequirementAttribute : TypeFilterAttribute
{
    public ClaimRequirementAttribute(string claimType, string claimValue) : base(typeof(ClaimRequirementFilter))
    {
        Arguments = new object[] {new Claim(claimType, claimValue) };
    }
}

public class ClaimRequirementFilter : IAuthorizationFilter
{
    readonly Claim _claim;

    public ClaimRequirementFilter(Claim claim)
    {
        _claim = claim;
    }

    public void OnAuthorization(AuthorizationFilterContext context)
    {
        var hasClaim = context.HttpContext.User.Claims.Any(c => c.Type == _claim.Type && c.Value == _claim.Value);
        if (!hasClaim)
        {
            context.Result = new ForbidResult();
        }
    }
}


[Route("api/resource")]
public class MyController : Controller
{
    [ClaimRequirement(MyClaimTypes.Permission, "CanReadResource")]
    [HttpGet]
    public IActionResult GetResource()
    {
        return Ok();
    }
}
2020-05-19