【问题标题】:Custom security scenario in ASP.NET MVCASP.NET MVC 中的自定义安全方案
【发布时间】:2012-04-26 17:51:36
【问题描述】:

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

假设我们有员工、主管和部门经理。 员工和主管都根据他们所属的部门经理分配了 ManagerId。

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

有意义吗?

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

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 中输入它似乎是多余的,只是......嗯......我知道一定有更好的方法。

【问题讨论】:

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


    【解决方案1】:

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

    创建一个自定义的 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.
            }
        }
    }
    

    【讨论】:

    • 感谢您的回复。很有意思。我真的需要“Else”吗?我不能说 If(employee.managerId != user.managerId) throw new MyUnauthorizedException(); ......否则将触发实现此功能的方法。不 ?我错过了什么? if (employee.managerId == user.managerId) 语句中的内容有什么意义?
    • 不需要 else... 只是为了表明它将继续执行。
    【解决方案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,我将有额外的方法/参数来指定操作的基本性质(例如读取、写入、删除、创建等)。

    【讨论】:

    • 除了将我的 IF 逻辑放到单独的语句中之外,几乎相同?
    • 基本上。只是集中权限检查,所以它有点干。 ActionFilterAttribute 方法可能是最干净的方法,假设它适用于您的应用程序。您需要能够访问存储库(这并不难),但您还需要能够解码用于访问检查的对象(这可能更具挑战性)。
    猜你喜欢
    • 2011-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多