保护ASP.NET MVC3控制器/操作

时间:2011-07-05 17:57:14

标签: asp.net-mvc asp.net-mvc-3 security

我正在设计一个MVC 3应用程序,其中多个租户驻留在一个数据库中。

阻止用户在MVC中编辑/查看其他租户数据的最佳方法是什么? (即有人可以输入'/ People / Edit / 1'并编辑Id为1的人,无论他们是否属于租户数据)。

我知道我可以为每个控制器覆盖'OnActionExecuting(ActionExecutingContext filterContext)'但是,分别处理每个动作听起来很疯狂,取决于它是POST还是GET获取ID或OBJECT然后检查操作是允许的。

有更好的想法吗?

此外,我不想为每个租户创建不同的数据库或架构。

提前致谢。

3 个答案:

答案 0 :(得分:1)

不是将id传递给控制器​​,而是为实体编写一个自定义模型绑定器,它将从数据库中获取它。例如,假设您有以下模型:

public class Person
{
    public string Id { get; set; }
    ... some other properties
}

现在而不是:

[HttpPost]
public ActionResult Edit(string id)
{
    ...
}

写:

[HttpPost]
public ActionResult Edit(Person person)
{
    ...
}

然后为Person编写自定义模型绑定器:

public class PersonModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var id = bindingContext.ValueProvider.GetValue("id");
        // check if an id was provided and if the user is authenticated
        if (!controllerContext.HttpContext.User.Identity.IsAuthenticated || id == null)
        {
            throw new HttpException(403, "Forbidden");
        }
        var currentUser = controllerContext.HttpContext.User.Identity.Name;
        // fetch the person from your repository given the id and belonging 
        // to the currently authenticated user
        var person = _repository.GetPerson(id.AttemptedValue, currentUser);
        if (person == null)
        {
            // no person found matching
            throw new HttpException(403, "Forbidden");
        }
        return person;
    }
}

您将在Application_Start注册:

ModelBinders.Binders.Add(typeof(Person), new PersonModelBinder());

答案 1 :(得分:0)

原始回答

要快速解决问题,请使用guids而不是自动增加整数。然而,这只是推迟了这个问题。

您可以做的一件事就是角色您自己的授权attribuut http://msdn.microsoft.com/en-us/library/system.web.mvc.authorizeattribute.aspx或者您可以选择创建一个全局动作过滤器。 http://www.asp.net/mvc/tutorials/understanding-action-filters-cs

根据评论中的请求添加有关如何执行此操作的信息

public class MySuperFilter : ActionFilterAttribute
    {
        //Called by the MVC framework before the action method executes.
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            String user = filterContext.HttpContext.User.Identity.Name;
            int id = int.Parse(filterContext.RouteData.GetRequiredString("Id"));
            if (!IsValidUser(user,id))
            {
                filterContext.Result = new RedirectToRouteResult(
                        new RouteValueDictionary {{ "Controller", "YourController" },
                                      { "Action", "YourAction" } });


            }

            base.OnActionExecuting(filterContext);
        }

        private bool IsValidUser(string user,int id)
        {
            //Check if the user has acces to the page
            return true;
        }
    }

答案 2 :(得分:0)

这是一个非优雅的解决方案,但根据范围,它可能是最简单的。设计了一个类似的系统,对于多个租户数据的入口点相对较少,我们只是检查CurrentUser是被查询对象的所有者。我们的使用对象是具有所有者字段的公共基本接口,因此检查不会携带特定对象,而只是来自接口。如果存在不匹配,我们会抛出一个安全异常,并记录用户可能正在查询字符串,看看他们是否让我们的网站以多个生产网站的方式泄露数据。