12

您将用户输入验证放在 Web 表单应用程序的什么位置?

  1. 视图:JavaScript 客户端
  2. 控制器:服务器端语言(C#...)
  3. 模型:数据库(存储过程或依赖项)

我认为每个级别都需要验证:

  1. 用户是否输入了一个合理的值
    • 是日期实际日期,是数字实际数字...
  2. 再次执行 1. 中的所有检查,并检查恶意攻击(IE XSS 或 SQL 注入)
    • 1.中所做的检查主要是为了避免用户出错时服务器往返。
    • 由于它们是在 javascript 中在客户端完成的,因此您不能相信它们是在运行的。再次验证这些值将阻止一些恶意攻击。
  3. 是否满足依赖关系(即用户是否向有效问题添加了评论)
    • 一个好的界面使这些很难违反。如果有什么东西在这里被抓住了,那么事情就很不对劲了。

[受此响应的启发]

4

10 回答 10

8

我检查了所有层级,但我想说明我使用的验证技巧。

我在数据库层进行验证,对模型的适当约束将提供自动数据完整性验证。

这是大多数 Web 程序员似乎迷失的艺术。

于 2008-09-25T16:37:05.407 回答
5

模型中的验证,可选的 UI 中的自动化例程,从模型中获取提示并改善用户体验。

通过自动化例程,我的意思是用户界面中不应该有任何每个模型的验证代码。如果您有一个验证方法库,例如 RoR(具有 validates_presence_of :username 之类的方法),则控制器或视图应该能够读取这些方法并应用等效的 javascript(或任何方便的方法)。

这意味着您必须在 ui 中复制完整的验证库,或者如果您使用预先存在的映射,则至少提供一个映射。但是一旦完成,您就不必在模型之外编写任何验证逻辑。

于 2008-09-25T16:44:34.407 回答
4

可以在所有层进行验证。

验证来自 Web 表单的输入(所有字符串、转换为适当的类型等)与验证来自 Web 服务或 XML 文件等的输入不同。每一种都有自己的特殊情况。当然,您可以创建一个 Validator 助手类,从而将 Validation 外部化并允许它被视图共享。

然后你有DAO层验证 - 模型中是否有足够的数据来持久化(以满足非空约束等)等等。您甚至可以在数据库中设置检查约束(是 ('N', 'A', 'S', 'D') 等中的状态)。

于 2008-09-25T16:41:13.227 回答
3

这很有趣。我在模型中执行所有验证的时间最长,就在我认为的 DAL(数据访问层)之上。我的模型通常是在表数据网关之后使用 DAL 提供抽象和低级 API 的。

在 TDG 中,我将实现业务逻辑和验证,例如:

  1. 用户名是否为空
  2. 用户名 > 30 个字符
  3. 如果记录不存在,则返回错误

随着我的应用程序变得越来越复杂,我开始意识到大部分验证都可以在客户端使用 JavaScript 完成。所以我将大部分验证逻辑重构为 JS 并清理了我的模型。

然后我意识到服务器端验证(不是过滤/转义——我认为不同)应该在服务器中完成,并且只有客户端作为锦上添花。

因此,当我再次意识到,INPUT 验证/断言和业务规则/逻辑之间可能存在明显差异时,验证逻辑又回来了。

基本上,如果它可以在应用程序的客户端完成(使用 JS)我认为这是 INPUT 验证......如果它必须由模型完成(这个记录是否已经存在等?)然后我会考虑商业逻辑。令人困惑的是它们都保护了数据模型的完整性。

如果您不验证用户名的长度,那么如何阻止人们创建单字符用户名?

我还没有完全决定接下来把这个逻辑放在哪里,我认为这真的取决于你更喜欢什么,瘦控制器,重型模型,或者反之亦然......

在我的例子中,控制器往往更加以应用程序为中心,而如果精心制作模型,我经常可以在“其他”项目中重用,而不仅仅是在内部,所以我更喜欢保持模型的轻量级和较重的控制器。

真正驱使你朝任何一个方向发展的力量是个人观点、要求、经验等……

有趣的主题:)

于 2008-11-26T08:37:56.433 回答
3

验证必须在控制器中完成 - 这是唯一确保安全和响应的地方。

验证应该在视图中完成 - 它是联系点,将提供最好的 UE 并为您的服务器节省额外的工作。

验证在模型上完成 - 但仅限于特定核心级别的检查。数据库应该总是反映适当的约束,但是让它代表真正的验证是低效的,数据库也不总是可以用简单的约束来确定有效的输入。

于 2008-11-26T09:07:26.500 回答
2

所有验证都应该至少发生一次,这应该在中间层,无论是在您的值对象中(在 DDD 意义上,不要与 DTO 混淆),还是通过实体本身的业务对象。可以进行客户端验证以增强用户体验。我倾向于不进行客户端验证,因为我可以一次在表单上暴露所有错误的东西,但这只是我个人的偏好 可以进行数据库验证以确保数据完整性,以防你搞砸了逻辑中间层或后端的东西。

于 2008-09-25T16:45:45.697 回答
0

我只在视图和控制器中执行此操作,数据库通过您的数据类型和诸如此类的东西强制执行其中的一些操作,但我宁愿它在没有我发现错误的情况下走得那么远。

尽管您几乎回答了自己的问题,但要知道的重要一点是,您永远不能信任视图,尽管这是向用户提供反馈的最简单途径,因此您需要至少在一个级别上进行清理。

于 2008-09-25T16:43:52.520 回答
0

嗯,不确定。在我读到这篇文章之前,我会说控制器:瘦控制器,胖模型

http://blog.atrumfutura.com/archives/373-The-M-in-MVC-Why-Models-are-Misunderstood-and-Unappreciated.html

于 2009-08-09T21:19:35.730 回答
0

由于大多数验证依赖于业务规则,因此我在业务层上作为第三方工具类进行验证。还有其他类型的验证,例如用户输入,而它需要在控制器中进行,但您也可以将这些验证规则封装在第三方类中。实际上,这取决于要验证的内容。

客户端验证是次要的,只是为了构建一个轻量级的输入验证,但始终需要服务器端验证。你永远不能相信用户输入;)

.NET有很好的控件来构建验证,但业务层总是需要更好的方法来验证数据,而这些控件不足以完成这项任务。

于 2009-08-09T21:29:30.920 回答
-1

视图中的简单输入验证。模型中的完全验证。原因?如果您更改视图技术,并且验证在视图/控制器中,则必须为新视图重写验证。这可能会引入错误。把它放在模型中,所有视图都会重用它......

但是,正如我所说,视图中的简单验证是为了速度和易用性。

于 2009-09-16T15:27:04.417 回答