5

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 中包含该字段(通过剃刀)。

我认为答案可能是使用以下方法防止SubscribedThru在控制器中的 Edit 方法上进行绑定尝试:

[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 可以处理的值。令我惊讶的是,当我排除了绑定时,它甚至试图更新该字段。

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

我不能说我完全理解UpdateModelTryUpdateModel方法,想知道这是否是前进的方向?我和他们一起玩过,EF 会因为有重复的对象(相同的键)而引发错误,这令人困惑。

另外,我不清楚订阅数据是否从public ActionResult Edit(int id)控制器中的初始加载一直保留到最终[HttpPost] public ActionResult Edit(Subscription subscription)...方法,或者该行是否db.Entry(subscription).State = EntityState.Modified;尝试设置所有数据(我认为它只是设置一个指示“编辑-所以-EF-应该-保存-这个“)。

我是一名长期的 .NET 开发人员,刚刚进入我的第一个 ASP.NET MVC 项目,所以我可能忽略了一些令人痛苦的显而易见的事情。谢谢你的帮助!

4

2 回答 2

3

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

这正是你应该做的,以保持整洁。 AutoMapper减轻了ViewModel变化带来的麻烦。

于 2012-06-11T21:05:15.750 回答
1

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

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

于 2012-06-11T21:08:40.387 回答