Security » Authorization » 基于资源的授权

Resource Based Authorization 基于资源的授权

68 of 73 people found this helpful

Often authorization depends upon the resource being accessed. For example a document may have an author property. Only the document author would be allowed to update it, so the resource must be loaded from the document repository before an authorization evaluation can be made. This cannot be done with an Authorize attribute, as attribute evaluation takes place before data binding and before your own code to load a resource runs inside an action. Instead of declarative authorization, the attribute method, we must use imperative authorization, where a developer calls an authorize function within his own code.

授权经常要取决于访问的资源。例如,某个文档可能有一个作者属性。按照逻辑只允许该文档的作者进行更新,所以在做授权检查前,资源必须能从文档库中将其加载。这些功能靠Authorize属性是做不到的,因为属性检查发生在数据绑定前,同样也在相应方法内你编制的加载资源的代码之前发生。我们不能使用采用属性方法的声明性授权方式,而必须使用命令式授权,在其中,一个开发者在自己的代码中调用授权函数。

Authorizing within your code 代码中的授权

Authorization is implemented as a service, IAuthorizationService, registered in the service collection and available via dependency injection for Controllers to access.

要通过服务的形式实现授权------IAuthorizationService,在服务集合中进行注册,并在控制器中通过依赖注入的方法进行使用。

public class DocumentController : Controller
{
    IAuthorizationService _authorizationService;

    public DocumentController(IAuthorizationService authorizationService)
    {
        _authorizationService = authorizationService;
    }
}

 

IAuthorizationService has two methods, one where you pass the resource and the policy name and the other where you pass the resource and a list of requirements to evaluate.

IAuthorizationService 具有两个方法,一个是传入的资源和策略名称,另一个是传递的资源和待检查要求的列表。

Task<bool> AuthorizeAsync(ClaimsPrincipal user,
                          object resource,
                          IEnumerable<IAuthorizationRequirement> requirements);
Task<bool> AuthorizeAsync(ClaimsPrincipal user,
                          object resource,
                          string policyName);

 

To call the service load your resource within your action then call the AuthorizeAsync overload you require. For example

先在方法中调用资源服务,再调用AuthorizeAsync 加载你的需求。例如:

public async Task<IActionResult> Edit(Guid documentId)
{
    Document document = documentRepository.Find(documentId);

    if (document == null)
    {
        return new HttpNotFoundResult();
    }

    if (await authorizationService.AuthorizeAsync(User, document, "EditPolicy"))
    {
        return View(document);
    }
    else
    {
        return new ChallengeResult();
    }
}

 

Writing a resource based handler 编写基于资源的处理器

Writing a handler for resource based authorization is not that much different to writing a plain requirements handler. You create a requirement, and then implement a handler for the requirement, specifying the requirement as before and also the resource type. For example, a handler which might accept a Document resource would look as follows;

编写基于资源的授权处理程序与编写一个普通的需求处理程序并没有太大不同。先新建一个需求,然后执行该资源的处理程序,对该需求和资源类型进行指定。例如,一个可以接受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;
    }
}

 

Don’t forget you also need to register your handler in the ConfigureServices method;

不要忘记你也需要在ConfigureServices 方法中注册该处理程序。

services.AddSingleton<IAuthorizationHandler, DocumentAuthorizationHandler>();

 

Operational Requirements 可使用的要求

If you are making decisions based on operations such as read, write, update and delete, you can use the OperationAuthorizationRequirement class in the Microsoft.AspNetCore.Authorization.Infrastructure namespace. This prebuilt requirement class enables you to write a single handler which has a parameterized operation name, rather than create individual classes for each operation. To use it provide some operation names:

如果你基于诸如读、写、改、删等操作进行决策,你可使用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" };
}

 

Your handler could then be implemented as follows, using a hypothetical Document class as the resource;

你的处理程序然后就能像这样的被执行了,下面的例子用一个假象的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;
    }
}

 

You can see the handler works on OperationAuthorizationRequirement. The code inside the handler must take the Name property of the supplied requirement into account when making its evaluations.

你可查看按照OperationAuthorizationRequirement 工作的处理程序。当进行检查时,处理程序中的代码必须将需求提供的Name属性传递到账户中。

To call an operational resource handler you need to specify the operation when calling AuthorizeAsync in your action. For example

为了调用一个操作资源的处理程序,当调用方法中的AuthorizeAsync时,你需要对该项操作进行指定。例如:

if (await authorizationService.AuthorizeAsync(User, document, Operations.Read))
{
    return View(document);
}
else
{
    return new ChallengeResult();
}

 

This example checks if the User is able to perform the Read operation for the current document instance. If authorization succeeds the view for the document will be returned. If authorization fails returning ChallengeResult will inform any authentication middleware authorization has failed and the middleware can take the appropriate response, for example returning a 401 or 403 status code, or redirecting the user to a login page for interactive browser clients.

这个例子对User是否可以对当前文档进行Read操作进行检查。如果授权检查成功了,就会返回该文档的视图。如果失败了就返回ChallengeResult ,从而告知认证中间件授权失败,好让中间件采取适当的回应。例如返回401或403状态代码,或者把用户重定向到交互浏览器客户端的登录页面。

 

原文链接

public class DocumentController : Controller { IAuthorizationService _authorizationService; public DocumentController(IAuthorizationService authorizationService) { _authorizationService = authorizationService; } }

posted @ 2016-10-25 10:09  jqdy  阅读(758)  评论(0编辑  收藏  举报