本文翻译自:How do you create a custom AuthorizeAttribute in ASP.NET Core?

I'm trying to make a custom authorization attribute in ASP.NET Core. 我正在尝试在ASP.NET Core中创建自定义授权属性。 In previous versions it was possible to override bool AuthorizeCore(HttpContextBase httpContext) . 在以前的版本中,可以重写bool AuthorizeCore(HttpContextBase httpContext) But this no longer exists in AuthorizeAttribute . 但这在AuthorizeAttribute不再存在。

What is the current approach to make a custom AuthorizeAttribute? 制作自定义AuthorizeAttribute的当前方法是什么?

What I am trying to accomplish: I am receiving a session ID in the Header Authorization. 我要完成的工作:我在标题授权中收到一个会话ID。 From that ID I'll know whether a particular action is valid. 通过该ID,我将知道特定操作是否有效。


#1楼

参考:https://stackoom.com/question/281Jf/如何在ASP-NET-Core中创建自定义AuthorizeAttribute


#2楼

What is the current approach to make a custom AuthorizeAttribute 制作自定义AuthorizeAttribute的当前方法是什么

Easy: don't create your own AuthorizeAttribute . 简单:不要创建自己的AuthorizeAttribute

For pure authorization scenarios (like restricting access to specific users only), the recommended approach is to use the new authorization block: https://github.com/aspnet/MusicStore/blob/1c0aeb08bb1ebd846726232226279bbe001782e1/samples/MusicStore/Startup.cs#L84-L92 对于纯授权方案(如仅限制对特定用户的访问),建议的方法是使用新的授权块: https : //github.com/aspnet/MusicStore/blob/1c0aeb08bb1ebd846726232226279bbe001782e1/samples/MusicStore/Startup.cs#L84 -L92

public class Startup
{public void ConfigureServices(IServiceCollection services){services.Configure<AuthorizationOptions>(options =>{options.AddPolicy("ManageStore", policy => policy.RequireClaim("Action", "ManageStore"));});}
}public class StoreController : Controller
{[Authorize(Policy = "ManageStore"), HttpGet]public async Task<IActionResult> Manage() { ... }
}

For authentication, it's best handled at the middleware level. 对于身份验证,最好在中间件级别进行处理。

What are you trying to achieve exactly? 您到底想达到什么目标?


#3楼

I'm the asp.net security person. 我是asp.net安全人员。 Firstly let me apologize that none of this is documented yet outside of the music store sample or unit tests, and it's all still being refined in terms of exposed APIs. 首先,我很抱歉,除了音乐商店样本或单元测试之外,没有任何文档被记录下来,并且仍然在公开的API方面对其进行了完善。 Detailed documentation is here . 详细的文档在这里 。

We don't want you writing custom authorize attributes. 我们不希望您编写自定义授权属性。 If you need to do that we've done something wrong. 如果您需要这样做,我们做错了。 Instead, you should be writing authorization requirements . 相反,您应该编写授权要求

Authorization acts upon Identities. 授权作用于身份。 Identities are created by authentication. 身份是通过身份验证创建的。

You say in comments you want to check a session ID in a header. 您在注释中说,您想检查标题中的会话ID。 Your session ID would be the basis for identity. 您的会话ID将成为身份的基础。 If you wanted to use the Authorize attribute you'd write an authentication middleware to take that header and turn it into an authenticated ClaimsPrincipal . 如果您想使用Authorize属性,则可以编写身份验证中间件来获取该标头并将其转换为经过身份验证的ClaimsPrincipal You would then check that inside an authorization requirement. 然后,您将在授权要求中进行检查。 Authorization requirements can be as complicated as you like, for example here's one that takes a date of birth claim on the current identity and will authorize if the user is over 18; 授权要求可以任意复杂,例如,这里要求以当前身份声明出生日期,并在用户超过18岁时进行授权;

public class Over18Requirement : AuthorizationHandler<Over18Requirement>, IAuthorizationRequirement
{public override void Handle(AuthorizationHandlerContext context, Over18Requirement requirement){if (!context.User.HasClaim(c => c.Type == ClaimTypes.DateOfBirth)){context.Fail();return;}var dateOfBirth = Convert.ToDateTime(context.User.FindFirst(c => c.Type == ClaimTypes.DateOfBirth).Value);int age = DateTime.Today.Year - dateOfBirth.Year;if (dateOfBirth > DateTime.Today.AddYears(-age)){age--;}if (age >= 18){context.Succeed(requirement);}else{context.Fail();}}}
}

Then in your ConfigureServices() function you'd wire it up 然后在您的ConfigureServices()函数中将其连接起来

services.AddAuthorization(options =>
{options.AddPolicy("Over18", policy => policy.Requirements.Add(new Authorization.Over18Requirement()));
});

And finally, apply it to a controller or action method with 最后,通过以下方式将其应用于控制器或操作方法

[Authorize(Policy = "Over18")]

#4楼

You can create your own AuthorizationHandler that will find custom attributes on your Controllers and Actions, and pass them to the HandleRequirementAsync method. 您可以创建自己的AuthorizationHandler,以在Controllers和Actions上找到自定义属性,并将它们传递给HandleRequirementAsync方法。

public abstract class AttributeAuthorizationHandler<TRequirement, TAttribute> : AuthorizationHandler<TRequirement> where TRequirement : IAuthorizationRequirement where TAttribute : Attribute
{protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, TRequirement requirement){var attributes = new List<TAttribute>();var action = (context.Resource as AuthorizationFilterContext)?.ActionDescriptor as ControllerActionDescriptor;if (action != null){attributes.AddRange(GetAttributes(action.ControllerTypeInfo.UnderlyingSystemType));attributes.AddRange(GetAttributes(action.MethodInfo));}return HandleRequirementAsync(context, requirement, attributes);}protected abstract Task HandleRequirementAsync(AuthorizationHandlerContext context, TRequirement requirement, IEnumerable<TAttribute> attributes);private static IEnumerable<TAttribute> GetAttributes(MemberInfo memberInfo){return memberInfo.GetCustomAttributes(typeof(TAttribute), false).Cast<TAttribute>();}
}

Then you can use it for any custom attributes you need on your controllers or actions. 然后,您可以将其用于控制​​器或操作上所需的任何自定义属性。 For example to add permission requirements. 例如添加权限要求。 Just create your custom attribute. 只需创建您的自定义属性。

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public class PermissionAttribute : AuthorizeAttribute
{public string Name { get; }public PermissionAttribute(string name) : base("Permission"){Name = name;}
}

Then create a Requirement to add to your Policy 然后创建一个要求以添加到您的策略中

public class PermissionAuthorizationRequirement : IAuthorizationRequirement
{//Add any custom requirement properties if you have them
}

Then create the AuthorizationHandler for your custom attribute, inheriting the AttributeAuthorizationHandler that we created earlier. 然后,为您的自定义属性创建AuthorizationHandler,并继承我们先前创建的AttributeAuthorizationHandler。 It will be passed an IEnumerable for all your custom attributes in the HandleRequirementsAsync method, accumulated from your Controller and Action. 将为HandleRequirementsAsync方法中的所有自定义属性传递一个IEnumerable,该IEnumerable是从Controller和Action累积的。

public class PermissionAuthorizationHandler : AttributeAuthorizationHandler<PermissionAuthorizationRequirement, PermissionAttribute>
{protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionAuthorizationRequirement requirement, IEnumerable<PermissionAttribute> attributes){foreach (var permissionAttribute in attributes){if (!await AuthorizeAsync(context.User, permissionAttribute.Name)){return;}}context.Succeed(requirement);}private Task<bool> AuthorizeAsync(ClaimsPrincipal user, string permission){//Implement your custom user permission logic here}
}

And finally, in your Startup.cs ConfigureServices method, add your custom AuthorizationHandler to the services, and add your Policy. 最后,在Startup.cs ConfigureServices方法中,将自定义AuthorizationHandler添加到服务中,然后添加Policy。

        services.AddSingleton<IAuthorizationHandler, PermissionAuthorizationHandler>();services.AddAuthorization(options =>{options.AddPolicy("Permission", policyBuilder =>{policyBuilder.Requirements.Add(new PermissionAuthorizationRequirement());});});

Now you can simply decorate your Controllers and Actions with your custom attribute. 现在,您可以使用自定义属性简单地装饰控制器和动作。

[Permission("AccessCustomers")]
public class CustomersController
{[Permission("AddCustomer")]IActionResult AddCustomer([FromBody] Customer customer){//Add customer}
}

#5楼

The approach recommended by the ASP.Net Core team is to use the new policy design which is fully documented here . ASP.Net Core团队推荐的方法是使用新的策略设计, 在此将其详细记录。 The basic idea behind the new approach is to use the new [Authorize] attribute to designate a "policy" (eg [Authorize( Policy = "YouNeedToBe18ToDoThis")] where the policy is registered in the application's Startup.cs to execute some block of code (ie ensure the user has an age claim where the age is 18 or older). 新方法的基本思想是使用新的[Authorize]属性来指定一个“策略”(例如[Authorize( Policy = "YouNeedToBe18ToDoThis")] ,该策略已在应用程序的Startup.cs中注册以执行某些代码(即确保用户具有18岁或18岁以上的年龄声明)。

The policy design is a great addition to the framework and the ASP.Net Security Core team should be commended for its introduction. 策略设计是对框架的重要补充,ASP.Net Security Core团队的引入值得赞扬。 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 (eg options.AddPolicy("CanUpdateOrder", policy => policy.RequireClaim(MyClaimTypes.Permission, "CanUpdateOrder)); ), or writing some code to perform these registrations at run time (eg 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. 如果应用程序可能具有数百个离散权限来管理单个REST资源(“ CanCreateOrder”,“ CanReadOrder”,“ CanUpdateOrder”,“ CanDeleteOrder”等)上的CRUD操作,则新方法要么需要重复的一对一操作,要么一种策略名称与声明名称之间的映射(例如options.AddPolicy("CanUpdateOrder", policy => policy.RequireClaim(MyClaimTypes.Permission, "CanUpdateOrder)); ),或编写一些代码以在运行时执行这些注册(例如,从数据库中读取所有索赔类型,然后循环执行上述调用。)在大多数情况下,这种方法的问题是不必要的开销。

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

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: 以下是使用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();}
}

#6楼

Based on Derek Greer GREAT answer, i did it with enums. 基于Derek Greer GREAT的答案,我使用枚举来做到这一点。

Here is an example of my code: 这是我的代码示例:

public enum PermissionItem
{User,Product,Contact,Review,Client
}public enum PermissionAction
{Read,Create,
}public class AuthorizeAttribute : TypeFilterAttribute
{public AuthorizeAttribute(PermissionItem item, PermissionAction action): base(typeof(AuthorizeActionFilter)){Arguments = new object[] { item, action };}
}public class AuthorizeActionFilter : IAuthorizationFilter
{private readonly PermissionItem _item;private readonly PermissionAction _action;public AuthorizeActionFilter(PermissionItem item, PermissionAction action){_item = item;_action = action;}public void OnAuthorization(AuthorizationFilterContext context){bool isAuthorized = MumboJumboFunction(context.HttpContext.User, _item, _action); // :)if (!isAuthorized){context.Result = new ForbidResult();}}
}public class UserController : BaseController
{private readonly DbContext _context;public UserController( DbContext context) :base(){_logger = logger;}[Authorize(PermissionItem.User, PermissionAction.Read)]public async Task<IActionResult> Index(){return View(await _context.User.ToListAsync());}
}

如何在ASP.NET Core中创建自定义AuthorizeAttribute?相关推荐

  1. 如何在ASP.NET Core中编写自定义日志记录提供程序

    目录 介绍 如何实现所需的接口 基础类和附件 FileLoggerProvider具体类及其附件 1. ConfigureLogging() 2. appsettings.json文件 介绍 源代码可 ...

  2. 在ASP.NET Core中创建自定义端点可视化图

    在上篇文章中,我为构建自定义端点可视化图奠定了基础,正如我在第一篇文章中展示的那样.该图显示了端点路由的不同部分:文字值,参数,动词约束和产生结果的端点: 在本文中,我将展示如何通过创建一个自定义的D ...

  3. 如何在ASP.NET Core中自定义Azure Storage File Provider

    主题:如何在ASP.NET Core中自定义Azure Storage File Provider 作者: Lamond Lu 地址:  https://www.cnblogs.com/lwqlun/ ...

  4. asp绑定gridview属性_如何在ASP.NET Core中自定义Azure Storage File Provider

    主题:如何在ASP.NET Core中自定义Azure Storage File Provider 作者: Lamond Lu 地址:  https://www.cnblogs.com/lwqlun/ ...

  5. 如何在 ASP.NET Core 中使用 HttpClientFactory ?

    ASP.Net Core 是一个开源的,跨平台的,轻量级模块化框架,可用它来构建高性能的Web程序,这篇文章我们将会讨论如何在 ASP.Net Core 中使用 HttpClientFactory. ...

  6. 如何在 ASP.Net Core 中使用 Autofac

    依赖注入可以有效的实现对象之间的 松耦合 并能够实现代码的可测试和可维护性,ASP.Net Core 提供了一个极简版的容器实现对 依赖注入 的原生支持,然而内置的依赖注入容器相比成熟的 依赖注入容器 ...

  7. 如何在 ASP.Net Core 中使用 Configuration Provider

    ASP.NET Core 是一个开源的,跨平台的,精简的模块化框架,可用于构建高性能,可扩展的web应用程序, ASP.NET Core 中的数据配置常用 k-v 的形式存储,值得注意的是,新的数据配 ...

  8. 如何在 ASP.NET Core 中使用 Quartz.NET 执行任务调度

    当我们在web开发中,常常会遇到这么一个需求,在后台执行某一项具体的任务,具体的说就是这些任务必须在后台定时执行. Quartz.NET 是一个开源的 JAVA 移植版,它有着悠久的历史并且提供了强大 ...

  9. 如何在 Asp.Net Core 中对请求进行限流

    译文链接:https://www.infoworld.com/article/3442946/how-to-implement-rate-limiting-in-aspnet-core.html 在应 ...

最新文章

  1. 理性解读中国科技实力:不震惊式吹捧,也不全盘抹杀
  2. HTML5 geolocation和BaiduMap、BingMap、GoogleMap
  3. error LNK2019: 无法解析的外部符号 public: virtual void * __thiscall
  4. idea 整合SSM(spring spring-mvc mybatis)
  5. Scala基础教程(八):模式匹配、正则表达式
  6. window.onload事件
  7. Uvaoj10054 - The Necklace
  8. .png图片 阴影效果(fliter:drop-shadow属性)案例
  9. 不全屏放映ppt的方法
  10. java里equals_Java中equals和==的区别
  11. 本地拒绝服务漏洞修复建议
  12. UE4 虚幻引擎,蓝图Movement组件
  13. python可以爬wind的数据_Python:爬取上市公司公告-Wind-CSMAR
  14. 修改XMAPP中Apache的默认访问的主页
  15. 计算机word表格计算教程F9,word表格计算方法详解
  16. 使用itextsharp导出pdf表格排版问题
  17. IETESTER ie10.local 下载
  18. 小程序 加快安卓手机向蓝牙设备发送大数据
  19. 如何用MATLAB编写简单的音乐程序
  20. ROS 清理log文件

热门文章

  1. SAP abap smartforms 打印图片及注意事项
  2. 浅谈 Docker Daemon
  3. [c#.net]SuspendLayout 和 ResumeLayout
  4. 男人志-男性时尚杂志
  5. 基于clickhouse做用户画像,标签圈选
  6. Windows 系统 睡眠 休眠 混合睡眠 快速关机的技术说明
  7. 多曝光图像融合技术_文章和代码总结(Multi-Exposure Image fusion_papers_and_codes)
  8. 从女友和老妈的使用角度看精确率(precision)和召回率(recall)的不同
  9. python xgboost输出变量重要性_xgboost输出特征重要性排名和权重值
  10. Android自动化测试 - MonkeyRunner(二) 锤子便签测试脚本