MVC核心授权

时间:2016-11-22 19:26:24

标签: asp.net-core authorization

我正在将MVC Core用于我有以下问题的网站。

假设我有两组GroupA和GroupB,这些组有一些实体。实体要么属于GroupA,要么属于GroupB,但不能同时属于GroupA或GroupB。为了保护这些实体的更新,我已经定义了以下政策:

AuthorizationOptions.AddPolicy("UpdateEntityInGroupAPolicy", policy =>
{
    policy.RequireClaim("ClaimThatAllowsUpdatingEntityInGroupA");
});

此策略将确保想要更新GroupA中的实体的用户具有声明ClaimThatAllowsUpdatingEntityInGroupA。可以为GroupB创建一个类似的策略,声明ClaimThatAllowsUpdatingEntityInGroupB。

此外,假设GroupA具有id为5的实体,而GroupB具有id为10的实体。如果给定用户(具有声明ClaimThatAllowsUpdatingEntityInGroupA但未声明ClaimThatAllowsUpdatingEntityInGroupB)在url处更新id为5的实体:

http://example.com/entity/5/update

我现在如何确保用户不只是将网址中的5更改为10并实际更新GroupB中ID为10的其他实体?

我希望我对这个问题很清楚,并感谢您提供任何帮助:)

1 个答案:

答案 0 :(得分:0)

如果要使用Authorize属性,则无法执行此操作,因为授权过滤器不了解您的实体。因此,对于您的案例Resource Based Authorization似乎是正确的方法。

首先假设您的实体如下:

public class YourEntity
{
    public int Id { get; set; }
    public string Group { get; set; }
    //...
}

实施基于资源的授权

创建要求:

public class UpdateRequirement : IAuthorizationRequirement
{
}

为需求和实体

创建授权处理程序
public class YourEntityAuthorizationHandler : AuthorizationHandler<UpdateRequirement, YourEntity>
   {
       public override Task HandleRequirementAsync(AuthorizationHandlerContext context,
                                                   UpdateRequirement requirement,
                                                   YourEntity resource)
       {
           if(resource.Group == "GroupA" &&
              context.User.HasClaim("ClaimThatAllowsUpdatingEntityInGroupA"))
           {
               context.Succeed(requirement);
           }
           else if(resource.Group == "GroupB" &&
              context.User.HasClaim("ClaimThatAllowsUpdatingEntityInGroupB"))
           {
               context.Succeed(requirement);
           }
           return Task.CompletedTask;
       }
   }

最后在控制器逻辑中使用它:

    public async Task<IActionResult> Update([FromServices]IAuthorizationService authorizationService, int id)
    {
        var entity= _entityRepository.Get(id);

        if (entity == null)
        {
            return new NotFoundResult();
        }

        if (await _authorizationService.AuthorizeAsync(User, entity, new UpdateRequirement()))
        {
            return View(entity);
        }
        else
        {
            return new ChallengeResult();
        }
    }

另见@ blowdart的example