MVC 3 RTM。拥有一个具有AllowHtml属性的模型。在我的控制器操作中,如果操作将FormCollection作为参数,则会抛出异常:
[HttpPost]
public ActionResult Edit(FormCollection collection, int id)
{
var myEntity = _myRepo.Get(id);
TryUpdateModel(myEntity);
return DoSave(myEntity);
}
潜在危险的Request.Form 从客户端检测到值
但是,如果我的控制器操作使用对象而不是FormCollection,则不会抛出异常。
[HttpPost]
public ActionResult Edit(MyEntity postedEntity, int id)
{
var myEntity = _myRepo.Get(id);
TryUpdateModel(myEntity);
return DoSave(myEntity);
}
我已经设置了
的httpRuntime requestValidationMode = “2.0”
使用FormCollection时为什么会失败?
答案 0 :(得分:9)
您无法将AllowHtml
与FormCollection
一起使用。您可以使用[ValidateInput]
属性,但显然禁用所有值的验证:
[HttpPost]
[ValidateInput(false)]
public ActionResult Edit(FormCollection collection, int id)
{
var myEntity = _myRepo.Get(id);
TryUpdateModel(objective);
return DoSave(objective);
}
据说我会使用以下内容:
[HttpPost]
public ActionResult Edit(MyEntity entity)
{
if (ModelState.IsValid)
{
_myRepo.Save(entity);
return RedirectToAction("Success");
}
return View(entity);
}
答案 1 :(得分:2)
出于安全原因,简单地禁用验证不是一个很好的解决方案,因为您无意中完全禁用了该操作方法的安全性。
当您只需要一个GET或POST值时,这非常烦人 - 例如,如果您的GET / POST数据中存在任何的HTML值,Request.Params["xyz"]
将会抛出,甚至如果您发布的"xyz"
值不包含HTML。
(从最新的MVC 3.1版本开始就是如此。)
为了解决这个问题,我使用以下方法扩展了我的Controller基类:
/// <summary>
/// Gets a value from the current Controller's ValueProvider, bypassing post-data validation.
/// </summary>
public string GetUnvalidatedValue(string key)
{
ValueProviderResult result;
if (ValueProvider is IUnvalidatedValueProvider)
{
result = ((IUnvalidatedValueProvider)ValueProvider)
.GetValue(key, skipValidation: true);
}
else
{
result = ValueProvider.GetValue(key);
}
return result == null ? null : result.AttemptedValue;
}
这有效地允许您在绕过验证的同时获得单独的GET / POST值。
我认为这比完全关闭验证更好,更安全,更正确 - 您的应用程序确实可以从增加的安全性中受益,即使它的实现方式妨碍了,并且显然很难绕过它。
(我认为这不是设计,或者至少不是非常良好的设计......)