翻译如下:
通常授权取决于正在访问的资源。 例如,文档可以具有作者属性。 将只允许文档作者对其进行更新,因此必须在进行授权评估之前从文档存储库加载资源。 这不能使用Authorize属性来完成,因为属性评估发生在数据绑定之前,以及您自己的代码加载资源之前在一个动作中运行。 而不是声明性授权,属性方法,我们必须使用命令式授权,开发人员在其自己的代码中调用授权函数。
编写一个资源处理程序
为基于资源的授权编写处理程序与编写一个简单的需求处理程序没有太大的不同。 您创建一个需求,然后为需求实现一个处理程序,指定前面的需求以及资源类型。 例如,可能接受Document资源的处理程序将如下所示:
public class DocumentAuthorizationHandler : AuthorizationHandler<MyRequirement, Document> { public override Task HandleRequirementAsync(AuthorizationHandlerContext context, MyRequirement requirement, Document resource) { // Validate the requirement against the resource and identity. return Task.CompletedTask; } }
不要忘记你还需要在ConfigureServices方法中注册你的处理程序;
services.AddSingleton<IAuthorizationHandler, DocumentAuthorizationHandler>();
操作要求
如果您根据读取,写入,更新和删除等操作进行授权决策,则可以在Microsoft.AspNetCore.Authorization.Infrastructure命名空间中使用OperationAuthorizationRequirement类。 这个预构建的类使您能够编写具有参数化操作名称的单个处理程序,而不是为每个操作创建单独的类。 要使用它提供一些操作名称:
public static class Operations { public static OperationAuthorizationRequirement Create = new OperationAuthorizationRequirement { Name = "Create" }; public static OperationAuthorizationRequirement Read = new OperationAuthorizationRequirement { Name = "Read" }; public static OperationAuthorizationRequirement Update = new OperationAuthorizationRequirement { Name = "Update" }; public static OperationAuthorizationRequirement Delete = new OperationAuthorizationRequirement { Name = "Delete" }; }
然后,您的处理程序可以如下实现,使用假设的Document类作为资源;
public class DocumentAuthorizationHandler : AuthorizationHandler<OperationAuthorizationRequirement, Document> { public override Task HandleRequirementAsync(AuthorizationHandlerContext context, OperationAuthorizationRequirement requirement, Document resource) { // Validate the operation using the resource, the identity and // the Name property value from the requirement. return Task.CompletedTask; } }
您可以看到处理程序在操作授权要求上工作。 处理程序中的代码在进行评估时必须考虑提供的需求的Name属性。
要调用操作资源处理程序,您需要在操作中调用AuthorizeAsync时指定操作。 例如:
if (await authorizationService.AuthorizeAsync(User, document, Operations.Read)) { return View(document); } else { return new ChallengeResult(); }
此示例检查用户是否能够对当前文档实例执行读取操作。 如果授权成功,将返回文档的视图。 如果授权失败返回ChallengeResult将通知任何认证中间件授权失败,中间件可以采取适当的响应,例如返回401或403状态码,或将用户重定向到交互式浏览器客户端的登录页面。