这是一个观点:
@model ModelValidation.Models.Appointment
@{
ViewBag.Title = "Make a Booking";
}
<h2>
Book an Appointment</h2>
@using (Html.BeginForm())
{
<p>
@Html.LabelFor(m => m.ClientName, "Your name: ") @Html.EditorFor(m => m.ClientName)
</p>
<p>
@Html.LabelFor(m => m.Date, "Appointment Date: ") @Html.EditorFor(m => m.Date)
</p>
<p>
@Html.EditorFor(m => m.TermsAccepted) @Html.LabelFor(m => m.TermsAccepted, "I accept the terms & conditions")
</p>
<input type="submit" value="Make Booking" />
}
这是Appointment类:
public class Appointment
{
public string ClientName { get; set; }
[DataType(DataType.Date)]
public DateTime Date { get; set; }
public bool TermsAccepted { get; set; }
}
如果我进入ClientName编辑器,就像这样:
<b>asdf</b>
按下“Make Booking”按钮(提交)后,我收到以下异常:
[HttpRequestValidationException (0x80004005): potentilly dangerous value of Request.Form has been received from the client (ClientName="<b>asdf</b>").]
System.Web.HttpRequest.ValidateString(String value, String collectionKey, RequestValidationSource requestCollection) +8755668
Microsoft.Web.Infrastructure.DynamicValidationHelper.<>c__DisplayClass12.<ReplaceCollection>b__d(String value, String key) +79
Microsoft.Web.Infrastructure.DynamicValidationHelper.LazilyEvaluatedNameObjectEntry.ValidateObject() +89
Microsoft.Web.Infrastructure.DynamicValidationHelper.LazilyValidatingHashtable.get_Item(Object key) +54
System.Collections.Specialized.NameObjectCollectionBase.FindEntry(String key) +20
System.Collections.Specialized.NameValueCollection.GetValues(String name) +8
System.Web.Mvc.ValueProviderResultPlaceholder.GetResultFromCollection(String key, NameValueCollection collection, CultureInfo culture) +20
System.Web.Mvc.<>c__DisplayClass4.<.ctor>b__0() +16
System.Lazy`1.CreateValue() +361
System.Lazy`1.LazyInitValue() +9591042
System.Lazy`1.get_Value() +89
System.Web.Mvc.NameValueCollectionValueProvider.GetValue(String key, Boolean skipValidation) +68
System.Web.Mvc.ValueProviderCollection.GetValueFromProvider(IValueProvider provider, String key, Boolean skipValidation) +55
System.Web.Mvc.<>c__DisplayClass9.<GetValue>b__4(IValueProvider provider) +33
System.Linq.WhereSelectEnumerableIterator`2.MoveNext() +151
System.Linq.WhereSelectEnumerableIterator`2.MoveNext() +177
System.Linq.Enumerable.FirstOrDefault(IEnumerable`1 source) +4187840
System.Web.Mvc.ValueProviderCollection.GetValue(String key, Boolean skipValidation) +272
System.Web.Mvc.DefaultModelBinder.BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) +385
System.Web.Mvc.DefaultModelBinder.GetPropertyValue(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, IModelBinder propertyBinder) +17
System.Web.Mvc.DefaultModelBinder.BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor) +399
System.Web.Mvc.DefaultModelBinder.BindProperties(ControllerContext controllerContext, ModelBindingContext bindingContext) +93
System.Web.Mvc.DefaultModelBinder.BindComplexElementalModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Object model) +53
System.Web.Mvc.DefaultModelBinder.BindComplexModel(ControllerContext controllerContext, ModelBindingContext bindingContext) +1367
System.Web.Mvc.DefaultModelBinder.BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) +449
System.Web.Mvc.ControllerActionInvoker.GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor) +317
System.Web.Mvc.ControllerActionInvoker.GetParameterValues(ControllerContext controllerContext, ActionDescriptor actionDescriptor) +117
System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +343
System.Web.Mvc.Controller.ExecuteCore() +116
System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +97
System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext) +10
System.Web.Mvc.<>c__DisplayClassb.<BeginProcessRequest>b__5() +37
System.Web.Mvc.Async.<>c__DisplayClass1.<MakeVoidDelegate>b__0() +21
System.Web.Mvc.Async.<>c__DisplayClass8`1.<BeginSynchronous>b__7(IAsyncResult _) +12
System.Web.Mvc.Async.WrappedAsyncResult`1.End() +62
System.Web.Mvc.<>c__DisplayClasse.<EndProcessRequest>b__d() +50
System.Web.Mvc.SecurityUtil.<GetCallInAppTrustThunk>b__0(Action f) +7
System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action) +22
System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +60
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8862381
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +184
据我所知,razor视图引擎默认编码所有用户输入。 那我为什么要这个?
在调用目标POST操作方法之前抛出异常。 或者我错过了什么?
答案 0 :(得分:4)
编辑:
抱歉读错了。
默认情况下,MVC框架会尝试保护您免受危险输入,例如html。如果您以后重新渲染它,可以用它来攻击您的网站。见Cross Site Scripting
如果您想接受HTML,就像您为名称输入的值一样,您必须明确告诉它不要验证该输入。
像:
[HttpPost]
[ValidateInput(false)]
public ActionResult Save()
{
// ...method body
}
除非是特定要求,否则我当然会建议不要这样做。
答案 1 :(得分:2)
在数据层中存储HTML技术上没有任何问题,但它会增加您使用恶意HTML /脚本的xss(跨站点脚本)攻击。
在ClientName属性上使用
[AllowHtml]属性。然后在保存之前使用Microsoft WPL or Web Protection Library中的反xss库并使用
Sanitizer.GetSafeHtmlFragment(clientName)对其进行清理(不编码!),然后再保存到数据库中。
如果您需要有关请求验证和xss攻击的更多扩展信息,请参阅我的pluralsight.com hack校对课程。