我正在尝试在 ASP.NET Core 中创建自定义授权属性。在以前的版本中,可以覆盖bool AuthorizeCore(HttpContextBase httpContext). 但这不再存在于AuthorizeAttribute.
bool AuthorizeCore(HttpContextBase httpContext)
AuthorizeAttribute
当前制作自定义 AuthorizeAttribute 的方法是什么?
我要完成的工作:我在标头授权中收到一个会话 ID。从那个 ID 我会知道一个特定的动作是否有效。
ASP.Net Core 团队推荐的方法是使用此处完整记录的新策略设计。新方法背后的基本思想是使用新[Authorize]属性来指定“策略”(例如[Authorize( Policy = "YouNeedToBe18ToDoThis")],在应用程序中注册策略Startup.cs以执行某些代码块(即确保用户有年龄声明,其中年龄为 18 岁或较旧)。
[Authorize]
[Authorize( Policy = "YouNeedToBe18ToDoThis")]
Startup.cs
策略设计是对框架的一个很好的补充,应该赞扬 ASP.Net 安全核心团队的引入。也就是说,它并不适合所有情况。这种方法的缺点是它无法为简单地断言给定控制器或动作需要给定声明类型的最常见需求提供方便的解决方案。在应用程序可能具有数百个离散权限管理单个 REST 资源(“CanCreateOrder”、“CanReadOrder”、“CanUpdateOrder”、“CanDeleteOrder”等)上的离散权限的情况下,新方法要么需要重复的一对一策略名称和声明名称之间的一种映射(例如options.AddPolicy("CanUpdateOrder", policy => policy.RequireClaim(MyClaimTypes.Permission, "CanUpdateOrder));),或者编写一些代码在运行时执行这些注册(例如,从数据库中读取所有声明类型并在循环中执行上述调用)。在大多数情况下,这种方法的问题在于它是不必要的开销。
options.AddPolicy("CanUpdateOrder", policy => policy.RequireClaim(MyClaimTypes.Permission, "CanUpdateOrder));
虽然 ASP.Net Core 安全团队建议永远不要创建自己的解决方案,但在某些情况下,这可能是开始时最谨慎的选择。
以下是一个实现,它使用IAuthorizationFilter提供一种简单的方式来表达给定控制器或操作的声明要求:
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(); } }