5

我有一个类似于日历的 ASP.NET MVC 应用程序。根据 NerdDinner 示例,我正在使用 UpdateMethod() 更新编辑页面的结果

在我的应用程序中,某些事件是完全可定制的,而某些事件只是部分可定制的。尽管用于编辑部分可自定义事件的编辑表单只有这些字段可用,但显然有人可以使用丢失的数据创建自己的表单并发布到我的网站。如果他们这样做,是什么阻止某人更改任何/所有字段?更糟糕的是,如果他们试图更改 id(主键)怎么办?

感觉 UpdateModel() 很容易受到非常基本的黑客攻击。我的恐惧是合理的还是我错过了什么?

// POST: /MyEvents/Edit/2
[AcceptVerbs(HttpVerbs.Post), Authorize]
public ActionResult Edit(int id, FormCollection formValues)
{
    MyEvent myevent = eventRepository.GetMyEvent(id);

    try
    {
        UpdateModel(myevent);
        eventRepository.Save();
        return RedirectToAction("Details", new { id = myevent.MyEventId });
    }
    catch
    {
        ModelState.AddRuleViolations(myevent.GetRuleViolations());
        return View(new MyEventFormViewModel(myevent));
    }
}
4

5 回答 5

9

您缺少有关“模型绑定安全性”的部分。您应该始终包含可由您的任何用户输入法更新的属性的白名单。

例如,来自 NerdDinner:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create( [Bind(Include="Title, Address")] Dinner dinner)
{

}

或者,如果您正在调用 UpdateModel,您可以创建一个允许属性的字符串数组,然后执行

UpdateModel(myObject, allowedProperties);

您可以锁定类本身,以便也只有某些属性是可更新的。

[Bind(Include="MyProp1,MyProp2,MyProp3")]
public partial class MyEntity { }
于 2009-10-01T20:00:58.057 回答
7

你的担心是对的。这称为批量分配。您可以通过使用BindAttribute标记您的类并设置Exclude / Include属性来保护您的代码。

于 2009-10-01T19:58:23.723 回答
4

有进取心/恶意的人完全有可能将字段映射到模型上的任何属性。有几种方法可以解决这个问题

最简单的是使用前面提到的 UpdateModel 的排除/包含属性重载。这样做的缺点是该方法只接受一个字符串数组,这有时意味着如果您进行任何重命名,您的代码就会不同步。

另一种方法是使用一个包含绑定字段的简单 DTO,然后您可以使用 DTO 并使用您的事件对象做您想做的事情,这显然增加了另一个类并且更加手动,但给您更多的控制

public ActionResult(int id, EditForm form) {
    MyEvent event = _eventRepository.GetMyEvent(id);
    event.Name = form.Name; //etc;
    if (User.IsInRole("Organiser")) {
        event.Date = form.Date;
    }
    return ...
}

另一种方法可能是通过 MyEvent 类的客户模型绑定器,它只绑定您想要的字段,但可能有点矫枉过正。

于 2009-10-01T20:09:30.177 回答
1

UpdateModel有一些重载,它们采用一组字符串命名属性来更新。这些重载只会更新命名属性。

可能还有其他更简单/更具声明性的方式来实现这一点,我不是 MVC 数据绑定方面的专家。

于 2009-10-01T19:59:51.187 回答
1

您可以在模型上标记应该被更新忽略的字段,或者使用其他UpdateModel重载之一传递包含/排除字段的列表。

于 2009-10-01T20:00:18.977 回答