导航到路由时如何确保用户拥有或属于资源(ASP.NET MVC)

时间:2010-08-25 14:36:24

标签: asp.net-mvc security

我想知道如何确保员工无法访问其他公司的信息。这不是关于将角色或权限应用于操作的基于身份验证/角色的问题,而是确保某人尝试访问的数据实际上属于他们。

用户属于某个部门,而该部门又属于公司。在下面的示例中,日历属于公司。如何确保用户只能在自己公司内编辑日历。

public ActionResult Edit(int? calendarId)
{
       ...
}

因此,当用户浏览/ Calendars / 55时,如何确保日历属于与用户相同的公司?因此,例如,您不能篡改URL并为属于另一家公司的日历添加ID。

方法1

public ActionResult Edit(int? calendarId)
{
    // get company that calendar belongs to
    int calCompanyId = ..
    if (CurrentUser.CompanyId != calCompanyId)
        return RedirectToAction(....); // cannot access resource

       ...
}

虽然这会起作用,但我想知道是否有更好的方法来处理这类问题。可能这不需要对所有控制器中的每一个动作进行检查。

是否存在用于解决此类问题的典型模式,您需要检查用户是否可以访问特定路径?我认为这对于拥有资源(公司,部门等)的应用程序来说是一个非常典型的问题,需要确保一个公司/用户无法访问其他公司的数据。

修改

正如@jfar所指出的,我可以使用CompanyId,但在大多数路线中都没有。我是否应该考虑改变我的路线结构,以便始终包含这些以使这些检查更容易?这样做是相当多的工作,但可能会“改变”路线。

在进一步思考这个问题之后,我认为在大多数行动中可能没有其他选择可以使用类似于'IsOwner(....)'的检查。其原因有两个;

  • 并非路由可访问的所有项目都有一个CompanyId属性,可以轻松地与用户的companyId进行比较,例如
  • 路径中的资源可能具有一个由公司拥有的departmentId。所以在这种情况下,我必须实现一个重载的'IsOwner',它知道要检查一个departmentId,或者跟一个对该部门拥有的公司的引用

在这个阶段,我想我会有一个'IsOwner'方法与@jfar发布的方法类似,可以检查直接链接到公司的资源是否归该公司所有,同时提供一些重载版本

CompanyOwns(CurrentUser.CompanyId, model);
DepartmentOwns(CurrentUser.departmentId, model);

我的所有数据库模型都实现了一个界面,使得通过id更容易找到它们。

public interface IAmIdentifiable<T>
{
   T Id { get; }
}

我可能会考虑为模型添加更多接口,以帮助上述辅助进程,如

public interface IAmOwnedByACompany
{
   int CompanyId { get; }
}

public interface IAmOwnedByADepartment
{
   int DepartmentId { get; }
}

这将使通过反射检查'IsOwner'类型方法中的对象更容易。我没有时间完全考虑这一点,但相信@jfar是正确的,当他在这种情况下说,在确定用户是否应该访问某个特定方法时,您确实需要对每种方法进行某种形式的手动检查route(代表资源)。通过实现一些接口和一些聪明的'IsOwner'类型方法,我希望这些检查非常简单。

1 个答案:

答案 0 :(得分:0)

您可以将其添加到基本控制器中。如果名为{CompanyId}的RouteParameter进入,则每个请求都会自动检查以确保CurrentUser.CompanyId与之匹配。

    protected User CurrentUser { get; set; }
    protected override void OnAuthorization(AuthorizationContext filterContext)
    {
        base.OnAuthorization(filterContext);

        if( RouteData.Values["CompanyId"] != null )
            if (CurrentUser.CompanyId != RouteData.Values["CompanyId"] )
                //Redirect to wherever

        //your not restricted from getting the companyid from the route
        //you could get the id from the logged in user, session, or any other method

    }

更新

您可以创建一个使用反射来检查实体是否拥有正确所有者的帮助器。即时编写的代码可能会出错。

    public bool IsOwner<T>(T model, int companyId)
    {
        var prop = model.GetType().GetProperty("CompanyId");

        if (prop == null)
            return false;

        var modelCompanyId = (int)prop.GetValue(model, null);

        return modelCompanyId == companyId;
    }