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

Pau*_*aag 7 c# asp.net asp.net-mvc

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

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

PrincipalPermission(SecurityAction.Demand, Role = "GroupLeader")
Run Code Online (Sandbox Code Playgroud)

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

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

[ClaimsPrincipalPermission(SecurityAction.Demand, Operation = "Manage", Resource = "Group")]
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

Chr*_*att 1

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

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

    ...

    public string Creator { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

然后:

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);
}
Run Code Online (Sandbox Code Playgroud)

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