1

我没有很多这方面的经验,我真的希望从你们那里得到一个好的建议。我需要实现以下安全场景,我想知道最好的方法。

想象一下,我们有员工、主管和部门经理。员工和主管都根据他们所属的部门经理分配了 ManagerId。

当主管用户登录时,我希望他只看到与他属于同一 ManagerId 的员工的记录。如果具有另一个 ManagerId 用户的另一个主管登录并在 url 中手动打卡其他员工的信息(例如: wwww.domain.com/employee/details/{id} ),因为他的 ManagerId != 员工的 ManagerId 我希望访问受到限制.

是否有意义 ?

我开始在所有 ActionMethods 上输入检查,例如:

public ActionResult Details(int id)
{
    var employee = employeeRepository.Get(id)
    var user = (CustomIdentity)ControllerContext.HttpContext.User.Identity;

    if(employee.managerId == user.managerId)
    {
        Do whatever...
    }   
    else    
    {
        Not allowed
    }
}

但是在所有 ActionMethods 中输入它似乎是多余的,只是..ehh...我知道必须有更好的方法。

4

2 回答 2

2

过去我有一个类似的问题,我会考虑每个对象的权限。我所做的是向对象添加一个成员,类似于:

public bool CanUserAccess(User user) {
    return managerId == user.managerId;
}

然后,在每个操作的顶部提供对受控资源的访问:

public ActionResult Details(int id)
{
    var employee = employeeRepository.Get(id)
    var user = (CustomIdentity)ControllerContext.HttpContext.User.Identity;
    if(!employee.CanUserAccess(user))
        return new HttpUnauthorizedResult();

    // Normal logic here
}

它当然不是完美的,但它确实集中了权限处理,并允许您在未来轻松增加复杂性(允许访问链,HR 的特殊规则等)。您还可以编写另一个重载/扩展来访问该User.Identity属性以实现更多自动化(或至少处理类型转换)。

由于我处理的是 ACL,因此我将有额外的方法/参数来指定操作的基本性质(例如读取、写入、删除、创建等)。

于 2012-04-26T18:31:46.653 回答
2

这是一个解决方案。它需要进行一些清理,但应该为您提供所需的一切。

创建一个自定义 ActionFilter,然后用它装饰您的方法。

[ManagerIdAuthentication]
public ActionResult Details(int id)
{
     // Gets executed if the filter allows it to go through.
}

下一个类可以在单独的库中创建,因此您可以将其包含在需要此验证的所有操作中。

public class ManagerIdAuthentication : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        // the next line needs improvement, only works on an httpGet since retrieves
        // the id from the url.  Improve this line to obtain the id regardless of 
        // the  method (GET, POST, etc.)
        var id = filterContext.HttpContext.Request.QueryString["id"];

        var employee = employeeRepository.Get(id);
        var user = filterContext.HttpContext.User.Identity;
        if (employee.managerId  == user.managerId)
        {
            var res = filterContext.HttpContext.Response;
            res.StatusCode = 402;
            res.End();
            filterContext.Result = new EmptyResult();  //may use content result if want to provide additional info in the error message.
        }
        else
        {
            // OK, let it through.
        }
    }
}
于 2012-04-26T18:36:21.527 回答