防止MVC 4过度发布的最佳方法是什么?
根据MS消息来源,[Bind]属性应该是通过阻止传入的表单值进入数据库来防止过度发布的最简单方法。随着最新版本的MVC& EF这似乎没有像预期/广告一样工作,除非我遗漏了一些重要的东西。
从 Wrox Professional ASP.NET MVC 4 (Jon Galloway的第7章),以下课程应防止过度发布:
[Bind(Exclude="IsAdmin")]
public class User
{
public int ID { get; set; }
public string FirstName { get; set; }
public bool IsAdmin { get; set; }
}
但是所有[Bind]属性都会阻止表单提交值绑定到模型。然后,模型具有空白/默认值,并将其写回数据库。在这种情况下,它会确保IsAdmin = false每次使用此模型调用.SaveChanges()。任何“真实”值都会被覆盖。这是一个巨大的安全失败。
替代语法 - 在编辑控制器动作参数中放置[Bind] - 完全相同:
public ActionResult Edit([Bind(Exclude = "IsAdmin")] User user)
当调用.SaveChanges()时,所有“true”值都会被覆盖,这与K. Scott Allen关于该主题的博客文章相矛盾:http://odetocode.com/blogs/scott/archive/2012/03/11/complete-guide-to-mass-assignment-in-asp-net-mvc.aspx
唯一的选择似乎是一系列专门的ViewModel,它们都与Automapper相连。虽然安全,但这似乎是一个非常令人头痛的问题,尤其是:
我知道有人会回应说你应该从不将数据模型绑定到视图,但这是默认的模板行为以及它在几乎所有文档中的显示方式。此外,MVC + EF应该让生活更容易,而不是更难,并且使用AutoMapper连接的ModelView类的海洋并不是我认为更容易的。
那么有人知道如何制作宣传的[Bind]功能吗?
答案 0 :(得分:5)
我想你可能会在这个场合误导Wrox的书。您描述的是Bind / Exclude属性的预期行为。请参阅http://msdn.microsoft.com/en-us/library/system.web.mvc.bindattribute.exclude(v=vs.108).aspx。
如果您不想将值绑定到模型上的每个属性,我相信ViewModel是他们的方式,即使您正确地指出它们是一种开销。然而,使用它们的优势是显着的,IMO在这种背景下,证明了额外的开发工作是合理的。例如:
Automapper是执行从实体到视图模型的映射的一个选项,但是如果您使用的是延迟加载,请注意。我发现Automapper不会按照我希望的方式处理EF Proxy类的更新。最后,我删除了AM并基于IMappable接口和通用实用程序类推出了自己的映射机制。在许多情况下,输入的代码并不比配置自动映射更多。
答案 1 :(得分:0)
如果你恢复到manuel模型绑定,你应该没有任何问题。如果您没有为“IsAdmin”输入输入,您的模型将保留其原始值。这增加了一些额外的代码,但是通过不生成不维护ViewModel来节省大量时间。
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(Guid id, FormCollection collection)
{
var user = db.Users.Find(id);
if (user != null)
TryUpdateModel(user);
else
return HttpNotFound();
if (ModelState.IsValid)
{
db.SaveChanges();
return RedirectToAction("Index");
}
return View(user);
}