我在ASP.NET MVC 2中广泛使用Data Annotation验证.这个新功能节省了大量时间,因为我现在能够在一个地方定义客户端验证和服务器端验证.然而,当我做一些详细的测试时,我意识到如果我单独依赖Data Annotation验证,那么很容易绕过服务器端验证.例如,如果我通过使用[Required]属性注释属性来定义必需字段并在表单中放置该必填字段的文本框,则用户可以简单地从DOM中删除文本框(可以通过Firebug轻松完成)现在,在Controller内的ModelBinding期间,不会在该属性上触发数据注释验证.为了确保触发"必需"验证,我可以在ModelBinding发生后重复验证,但后来我会重复我的验证逻辑.
每个人对验证的建议是什么?数据注释验证是否足够?或者是否需要重复验证以确保在所有情况下都能触发验证?
后续评论: 根据以下答案,我似乎不能单独依赖Model Binder和Data Annotation验证.由于我们得出结论认为需要额外的服务器端验证,我的服务层是否有一种简单的方法可以根据数据注释中定义的内容触发验证?看起来这将使我们两个词中最好的...我们不需要重复验证代码,但我们仍然会确保即使Model Binder没有触发它也会执行验证.
我将把这个后续评论作为一个单独的问题发布,因为它提出了一个与原始评论不同的问题.
我认为要对安全性保持警惕,您应该选择将服务器验证作为优先事项,并确保这始终是您的后备.您的服务器验证应该没有客户端验证.对于用户体验而言,客户端验证更多,对您的设计至关重要,它是次要的安全性.考虑到这一点,您会发现自己重复验证.目标通常是尝试设计您的应用程序,以便尽可能集成服务器和客户端验证,以减少在服务器和客户端上验证所需的工作.但请放心,你必须做到这两点.
如果绕过客户端验证(通过DOM操作)是避免服务器验证(您似乎在指示),则可能无法正确使用此实例的服务器验证.您应该在控制器操作或服务层中再次调用服务器验证.您描述的方案不应该破坏您的服务器验证.
使用您描述的场景,DataAnnotation属性方法应该足够了.您似乎只需要进行一些代码更改,以确保在提交表单时也调用服务器验证.
我将xVal与DataAnnotations配对,并编写了自己的Action过滤器,用于检查任何实体类型参数以进行验证.因此,如果回发中缺少某个字段,则此验证器将填充ModelState字典,因此模型无效.
先决条件:
我的实体/模型对象都实现了IObjectValidator
声明Validate()
方法的接口.
我的属性类被调用 ValidateBusinessObjectAttribute
xVal验证库
动作过滤器代码:
public void OnActionExecuting(ActionExecutingContext filterContext) { IEnumerable> parameters = filterContext.ActionParameters.Where >(p => p.Value.GetType().Equals(this.ObjectType ?? p.Value.GetType()) && p.Value is IObjectValidator); foreach (KeyValuePair param in parameters) { object value; if ((value = param.Value) != null) { IEnumerable errors = ((IObjectValidator)value).Validate(); if (errors.Any()) { new RulesException(errors).AddModelStateErrors(filterContext.Controller.ViewData.ModelState, param.Key); } } } }
我的控制器动作定义如下:
[ValidateBusinessObject] public ActionResult Register(User user, Company company, RegistrationData registrationData) { if (!this.ModelState.IsValid) { return View(); } ... }