【发布时间】:2019-07-17 11:25:17
【问题描述】:
我正在努力寻找一个很好的解决方案来进行自定义授权检查,而不必一遍又一遍地手动重复授权检查。
为了说明,假设我有以下 .net 核心 web api 设置,它有两个端点,一个用于 GET,一个用于 POST。我想检查(可能针对 db)用户是否有权查看资源,或有权创建资源。
这就是文档中提到的resource based authorization 看起来像这样:
[Authorize]
[ApiVersion ("1.0")]
[Route ("api/v{version:apiVersion}/[controller]")]
[ApiController]
public class ResourcesController : ControllerBase {
private readonly IAuthorizationService _authorizationService;
//..constructor DI
[HttpGet ("{resourceId}")]
public ActionResult<Resource> Get (Guid resourceId) {
var authorizationCheck = await _authorizationService.AuthorizeAsync (User, resourceId, ServiceOperations.Read);
if (!authorizationCheck.Succeeded) {
return Forbid ();
}
return Ok (ResourceRep.Get (resourceId));
}
[HttpPost]
public ActionResult<Resource> Post ([FromBody] Resource resource) {
var authorizationCheck = await _authorizationService.AuthorizeAsync (User, null, ServiceOperations.Write);
if (!authorizationCheck.Succeeded) {
return Forbid ();
}
return Ok (ResourceRep.Create (resource));
}
}
现在想象ServiceOperations 枚举有很长的受支持操作列表,或者有 100 个不同的端点,我将不得不在任何地方进行相同的检查,或者更糟糕的是,可能会忘记在我应该有的地方添加检查加了一张支票。而且在单元测试中也没有简单的方法来解决这个问题。
我曾想过使用属性,但正如文档所述:
属性评估发生在数据绑定之前和加载文档的页面处理程序或操作执行之前。由于这些原因,带有 [Authorize] 属性的声明式授权是不够的。相反,您可以调用自定义授权方法 — 一种称为命令式授权的样式。
因此,当检查本身需要不可用的参数(resourceId)时,我似乎无法使用授权策略并使用授权属性(很容易对它们进行单元测试)来装饰方法。
所以对于问题本身: 您如何一般使用命令式(基于资源的)授权而不必重复自己(这很容易出错)。我希望有如下属性:
[HttpGet ("{resourceId}")]
[AuthorizeOperation(Operation = ServiceOperations.Read, Resource=resourceId)]
public ActionResult<Resource> Get (Guid resourceId) {..}
[AuthorizeOperation(Operation = ServiceOperations.Write)]
[HttpPost]
public ActionResult<Resource> Post ([FromBody] Resource resource) {..}
【问题讨论】:
-
AuthorizeOperation 属性的实际用途是什么? [Authorize] 和 [AllowAnonymous] 在控制器和操作上可以互换,因此您可以通过这种方式微调您的需求。
标签: asp.net-core authorization