防止篡改ASP.NET MVC EF中的表单字段

时间:2012-06-11 21:01:25

标签: asp.net-mvc-3 security entity-framework-4.1

ASP.NET MVC 3中默认的强类型编辑页面通常会公开实体的所有字段。虽然这通常是可行的,但某些领域存在安全风险。例如,简化的杂志订阅实体可能如下所示:

public void Subscription() {
  public int Id { get; set; }
  public string Name { get; set; }
  public string Address { get; set; }
  public string City { get; set; }
  public string State { get; set; }
  public string Zip { get; set; }
  public DateTime SubscribedThru { get; set; }
}

例如,如果我提供编辑页面以允许用户更改自己的地址,那么包含SubscribedThru字段会带来安全风险,因为知识渊博的恶意用户可以通过伪造为自己提供10年的免费订阅日期(即使我使用@Html.HiddenFor(model => model.SubscribedThru)。所以我不会在编辑页面html(通过剃刀)中以任何方式包含该字段。

我认为答案可能是阻止对控制器中Edit方法的SubscribedThru进行绑定尝试,例如:

[HttpPost]
public ActionResult Edit([Bind(Exclude="SubscribedThru")] Subscription subscription) {
  if (ModelState.IsValid) {
    db.Entry(subscription).State = EntityState.Modified;
    db.SaveChanges();
    return RedirectToAction("Index");
    }
  }
  return View(subscription);
}

当我到达SaveChanges();行时,它会抛出错误The conversion of a datetime2 data type to a datetime data type resulted in an out-of-range value.我认为SubscribedThru日期(正确?)不存在,并且空值小于SQL Server可以处理的值。让我感到惊讶的是,当我将Binding排除在外时,它甚至会尝试更新该字段。

到目前为止,我最好的解决方案似乎是创建一个省略SubscribedThru日期的自定义ViewModel,但这似乎是很多重复的字段,验证等;如果可能的话,我想让一个字段SubscribedThru免于用户编辑。

我不能说我完全理解UpdateModelTryUpdateModel方法,并想知道这是否是一个方向?我和他们一起玩,EF因为有重复的对象(相同的密钥)而引发错误。

此外,我不清楚订阅数据是否从控制器中public ActionResult Edit(int id)的初始加载一直保留到最终[HttpPost] public ActionResult Edit(Subscription subscription)...方法,或者行{{1}尝试并设置所有数据(我认为它只是设置一个标志,表示“编辑 - 所以 - EF-should-save-this”)。

我是一名长期的.NET开发人员,刚刚进入我的第一个ASP.NET MVC项目,所以我可能会忽略一些非常明显的东西。谢谢你的帮助!

2 个答案:

答案 0 :(得分:3)

  

到目前为止,我最好的解决方案似乎是创建一个省略SubscribedThru日期的自定义ViewModel,但这似乎有很多重复的字段,验证等;

这正是你应该做的事情,以保持整洁和安全整洁。 AutoMapper可以缓解ViewModel变异性头痛。

答案 1 :(得分:1)

此页面包含使用TryUpdateModel更新模型的示例(清单4): http://www.asp.net/mvc/tutorials/older-versions/models-(data)/creating-model-classes-with-the-entity-framework-cs

您只能将允许编辑的字段列入白名单,这样可以消除安全风险。