如何在ASP.NET Core中创建自定义AuthorizeAttribute? [英] How do you create a custom AuthorizeAttribute in ASP.NET Core?

查看:628
本文介绍了如何在ASP.NET Core中创建自定义AuthorizeAttribute?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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

解决方案

ASP.Net Core团队建议的方法是使用新的策略设计,该设计在[Authorize( Policy = "YouNeedToBe18ToDoThis")],其中该策略已在应用程序的Startup.cs中注册,以执行一些代码块(即,确保用户拥有年满18岁的年龄索赔.

该策略设计是对该框架的重要补充,ASP.Net Security Core团队的引入值得赞扬.也就是说,它并不适合所有情况.这种方法的缺点在于,它不能为最简单的要求简单地断言给定的控制器或动作需要给定的索赔类型的最常见需求提供方便的解决方案.如果应用程序可能具有数百个离散的权限来管理单个REST资源上的CRUD操作("CanCreateOrder","CanReadOrder","CanUpdateOrder","CanDeleteOrder"等),则新方法要么需要重复的一对一操作,要么策略名称和声明名称(例如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();
    }
}

I'm trying to make a custom authorization attribute in ASP.NET Core. In previous versions it was possible to override bool AuthorizeCore(HttpContextBase httpContext). But this no longer exists in AuthorizeAttribute.

What is the current approach to make a custom AuthorizeAttribute?

What I am trying to accomplish: I am receiving a session ID in the Header Authorization. From that ID I'll know whether a particular action is valid.

解决方案

The approach recommended by the ASP.Net Core team is to use the new policy design which is fully documented here. The basic idea behind the new approach is to use the new [Authorize] attribute to designate a "policy" (e.g. [Authorize( Policy = "YouNeedToBe18ToDoThis")] where the policy is registered in the application's Startup.cs to execute some block of code (i.e. ensure the user has an age claim where the age is 18 or older).

The policy design is a great addition to the framework and the ASP.Net Security Core team should be commended for its introduction. That said, it isn't well-suited for all cases. The shortcoming of this approach is that it fails to provide a convenient solution for the most common need of simply asserting that a given controller or action requires a given claim type. In the case where an application may have hundreds of discrete permissions governing CRUD operations on individual REST resources ("CanCreateOrder", "CanReadOrder", "CanUpdateOrder", "CanDeleteOrder", etc.), the new approach either requires repetitive one-to-one mappings between a policy name and a claim name (e.g. options.AddPolicy("CanUpdateOrder", policy => policy.RequireClaim(MyClaimTypes.Permission, "CanUpdateOrder));), or writing some code to perform these registrations at run time (e.g. read all claim types from a database and perform the aforementioned call in a loop). The problem with this approach for the majority of cases is that it's unnecessary overhead.

While the ASP.Net Core Security team recommends never creating your own solution, in some cases this may be the most prudent option with which to start.

The following is an implementation which uses the IAuthorizationFilter to provide a simple way to express a claim requirement for a given controller or action:

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();
    }
}

这篇关于如何在ASP.NET Core中创建自定义AuthorizeAttribute?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆