MVC / ASP.Net记录级授权的最佳实践

时间:2014-09-23 15:19:41

标签: c# asp.net asp.net-mvc

在ASP.Net MVC网站内保持关注点分离的同时,是否有人对实施记录级授权的良好方法有任何建议?

使用PrincipalPermission,您可以使用以下方法修饰方法:

PrincipalPermission(SecurityAction.Demand, Role = "GroupLeader")

要求该页面的任何访问者都是固定角色“GroupLeader”的成员。

或者,您可以使用以下方法修饰方法:

[ClaimsPrincipalPermission(SecurityAction.Demand, Operation = "Manage", Resource = "Group")]

要求允许该页面的任何访问者一般管理一个组。

但是,这些都没有真正解决用户可能拥有编辑某些组的权限的情况,而不是其他组。据我所知,即使我实现了自定义ClaimsAuthorizationManager,也无法访问方法参数以进行条件授权。

此外,如果用户没有访问权限,上述两种方法都会抛出SecurityException,而不是允许方法将用户正常地重定向到解释发生了什么以及他们可能会做什么的页面必要的授权。

显然,我也意识到我只能将授权逻辑编码到方法本身并相应地重定向,但我宁愿把它分开,如果可能的话,并保持方法代码干净,只处理实际处理请求,并且能够在更通用的框架内工作。

那么,是否有一种“开箱即用”的方式来处理这种情况,或者我是否必须实现自定义IAuthorizationFilter?我认为我可以处理记录级授权和优雅重定向,但是在方法级别没有任何参数,它本质上是一个巨大的if ... else if语句。

1 个答案:

答案 0 :(得分:1)

处理这种情况最直接的方法是在您的实体上创建一个属性来存储实体的“所有者”或“创建者”。然后,当您查询对象时,您将按此过滤。例如:

public class Foo
{
    public int Id { get; set; }

    ...

    public string Creator { get; set; }
}

然后:

public ActionResult FooDetails(int id)
{
    var foo = db.Foos.SingleOrDefault(m => m.Id == id && m.Creator == User.Identity.Name);
    if (foo == null)
    {
        return new HttpNotFoundResult();
    }

    return View(foo);
}

通过授权过滤器处理此问题并不合适,因为您必须选择行来确定用户的权限。然后,您必须在操作中再次选择该行以将其发送到视图。此外,你必须做一些杂技,以使过滤器能够知道它应该从哪里选择,以便你甚至可以首先检查权限。在操作中,您已经在选择实体,因此只需根据用户是否“同时拥有”它来对其进行调整。