处理输入验证的专业/首选方式是啥
Posted
技术标签:
【中文标题】处理输入验证的专业/首选方式是啥【英文标题】:What is the profession / preferred way to handle input validation处理输入验证的专业/首选方式是什么 【发布时间】:2011-11-07 23:39:21 【问题描述】:我是 C# 和 SQL 的新手。但在过去的几年里,在大学里学习这两门课的时候,一个问题真的开始在我心中燃烧。这里是:
在我看来,确实有两种非常通用的方法来处理输入验证(即检查必填字段和正确范围内的数据等)。
第一个,也是传统的方式是:一旦您开发了您的 UI,并以某种方式将其连接到数据库后端。在用户界面上,您可以检查输入是否正确,例如空白文本框、数字范围,或者确保选中单选框或复选框等。
第二种,也是数据库开发中展示的方式是:对字段设置检查约束,例如不允许空值、唯一值,甚至范围和必填字段。
我的困境是这样的。鉴于在像 C# 这样的现代语言中,您可以进行一般的执行处理,并且还考虑到大多数数据库(如 SQL Server)都内置了大联盟容错,以处理与提交全部或不提交有关的数据更改。像这样的细节,到这个级别,除了最简单的程序外,其他任何东西都很难编程。
所以我的问题是,为什么不将所有需求直接构建到数据库后端的表中。利用前面提到的容错性,忘记编写 if 语句以确保输入正确的数据,而是在数据未提交时使用通用的 catch all execption 处理程序。
也许这就是它的完成方式,如果是这样,我真的很想知道。如果不是,为什么?我的偏好是尽可能避免编写代码。在更新方面,更少的代码、更少的调试和更少的问题。所以我倾向于采用让数据库后端完成工作的方法。这是通常正确的做法吗?
我知道一般的执行处理在资源方面被认为是“昂贵的”。但是一旦你超过 5 或 10 个 if 语句来处理不同的字段及其约束,那么只做一个通用的 execption 处理程序就必须更有效的代码。总体而言,它确实似乎更容易理解。 (至少我这样做的方式)。
感谢您对此的帮助。
【问题讨论】:
有趣,我自己也经常想知道这个 Where to put data management rules for complex data validation in ASP.NET MVC? 的可能重复项 这让我大吃一惊:“我的偏好是尽可能避免编写代码。更少的代码、更少的调试和更少的更新问题。” @jack-t-colton - 我从事软件开发,我们大学的主要规则是始终将其归咎于数据库人员! :-> 【参考方案1】:2 年后,我现在有了相当多的经验。我不会接受我的回答,因为这里的许多人都做得很好,我对他们的回答非常满意。但我想补充另一个重要的考虑因素,即回顾我的经历并没有在这里强调。随着我的进步,我也使用堆栈溢出作为参考,我总是发现自己回顾我的问题和答案,这是我想添加它的另一个原因。就像给我未来的自己写一个便条。
在那家公司工作时,我被要求构建一个可以完成工作 abc 的应用程序。有了这个,我还必须构建数据库的一部分。当我结束与公司的合作时,我了解到他们正在编写另一个将使用我的数据库的应用程序。实际上,我的观点是,正如许多人所指出的那样,数据是最重要的,当你离开时,你不知道如何访问它。
我也了解到有3个地方需要验证数据:
-
在实际的数据库上解释
服务器端代码与数据库或客户端验证不同
在客户端
还有一个担心。随着平板电脑和智能手机等新技术的出现。这是另一个必须实施验证的地方。第四次使用相同的规则(除非它是一个网络应用程序)。
后来我了解到,在 MVC 之前,我们有 CGI 表单,这与通过网络处理数据有关(我谦虚地承认硬件方面的无知)但从向我解释的情况来看,似乎甚至可能排在第 5 位进行验证(尽管我对此完全错误持开放态度)。
我认为,如果计算机科学领域的下一位大师能够找到一种方法将所有验证和确认抽象到一个地方,从而不必在一堆地方更改这些规则,他就会为自己出名。
最坏的情况:
-
数据库
服务器端代码
Web 应用程序的客户端代码
如果:
-
可能有本机客户端应用程序(即 windows、linux 或 mac(现在至少 6 个))
可能有各种手机应用程序(android、iPhone 和 win phone 名称 3,现在至少 9 个))
可能有一些 CGI 或其他内容
毫不夸张地说,总共有10多个地方,还有其他操作系统。
即使对于一个简单的年龄范围,这也会变得一团糟,但如果他们推出了一些新的电子邮件格式或其他复杂的验证,或者您必须更改一堆验证规则怎么办。现在你必须在至少 3 或 4 个地方修改它们,这本身就是不好的。
这样做的主要问题是您正在修改大量代码和基础架构,这些代码和基础架构已经投入、测试并且通常证明可以工作并交付给市场......
随着客户端数量的增长,修改经过良好测试的代码并不是一件好事。我认为这将是未来的一个主要问题。我想知道是否会有设计模式或最佳实践来解决它。如果有人知道,请告诉我。
【讨论】:
【参考方案2】:除了这里给出的所有答案,比如 UI 控件显着改善了用户的 UX,并且可以完全改变您的应用程序的“图像”,在 DB 上进行验证是为了将数据正确插入 DB,但在客户端必须这样做才能正确插入客户端数据。
以独立企业应用为例。一位在家工作的客户,他深夜在蒙古的笔记本上填写了 20 张发票。他回来后的第二天,将其与他的办公室 SAP 服务器同步。如果仅在数据同步期间才发现错误,您可以想象这种情况有多糟糕。
只是一个例子。我敢肯定,还有很多其他的。
祝你好运。
【讨论】:
很好的例子。但是surley,您将使用与服务器上存在的约束相同的约束在笔记本上对客户端数据库进行编程。这样做将确保您的数据可以在第二天提交而不会失败,同时仍然不需要 UI 背后的所有额外代码。谢谢你的回答。 @Francis:在我的帖子中说“编译”是指假设的客户填写一些仅执行数据库输入数据验证的应用程序的发票表格,我不是在谈论编程软件 :) 【参考方案3】:虽然我通常主张将尽可能多的数据放入数据库中(这意味着您可以对“原始”数据尽可能有信心),但这并不总是可行的,即使有强大的约束和SQL 中可用的触发器。
此外,还有一些高层次的“完整性”事物可能会随着时间而改变,并且总是在约束中具有时间动态条件是不现实的。即自 2007 年以来的所有 HR 记录的生日必须为非 NULL,但之前的记录可以保持为 NULL,但任何行都不能设置回 NULL。
我的意思是,您几乎永远不能将其全部放入数据库中。
尽你所能把东西放进去,把其他东西放在系统的更高层次上。数据库是任何系统的一个非常重要的部分,但它不是唯一的部分。只要它的设计有助于保护其边界并能够提供可靠的服务并保证它所说的将保证的内容,以便系统的其他部分可以依赖他们的假设,那么这就是你所能要求的最多了。
【讨论】:
【参考方案4】:好的,这就是您在两个地方都需要它的原因。
首先,数据的完整性应该是最重要的,并且可以直接在数据库表中更改数据(故意通过脚本来更新一百万个价格或意外,甚至是心怀不满或犯罪的员工试图破坏数据库或窃取公司)。因此,避免在数据库中直接使用约束是否鲁莽,导致数据不正确。
现在在用户界面级别,您希望防止用户浪费时间提交不良数据,并且您希望防止服务器和网络浪费时间尝试处理它,因此您在该级别编写检查。另外,如果您需要插入多个表并且不使用事务(您应该使用它,但我怀疑它发生的频率低于应有的频率),您不希望数据处于不一致状态。另外,用户讨厌当您尝试插入时它失败并告诉您 X 错误然后他们修复 X 现在 Y 错误但之前它是错误的,该过程只是没有达到之前的 Y。
【讨论】:
+1 - 数据本身绝对是最重要的,因此将约束和其他规则尽可能靠近数据(除了应用层的可用性)。如果您错过了应用程序中的某些内容,那么应用程序失败总比数据库损坏要好。 +1 - 我完全同意数据库的完整性。正如所指出的,数据库内置了极高的容错能力。因此,例如,不能输入部分记录集,它要么全有,要么全无。我也喜欢你关于网络流量的观点。这似乎是检查 UI 的一个很好的理由,没有它们,您必须提交数据并等待数据库告诉您它不正确。我必须学习使用事务。感谢您强调这一点,您能否推荐一个好的资源。最后你关于 X 和 Y 的观点都是错误的。好的设计是有意义的。谢谢你的回答 对于 SQL 服务器,请查看联机丛书中的事务以获取执行事务的 SQL 代码。还要看看 try catch。 经过一段时间的教导后,我接受了这个作为最终答案,因为您提到了我认为非常重要的两个要点。首先,数据完整性至关重要。其次是用户体验(好的设计)。通常,DB 人员会说让 UI 处理错误检查,减少网络流量,更安全,所有这些东西。虽然程序员说让数据库来处理它,但更多的容错性,事务管理等。您遇到了两个非常不同但更重要和更实际的考虑。不过,我仍然更喜欢让数据库来完成这项工作! :->【参考方案5】:您通常无法构建所有用于检查数据库的逻辑。此外,不充分验证用户输入也是让自己容易受到攻击的好方法。
在每种方法中编写较少保护代码的一种方法是“代码契约”,这是微软研究的产品。
所有输入都应在客户端和服务器端进行验证。总是。
还有一个巨大的捕获,很难判断哪个字段是错误的。所以你最终会在另一端编写大量哪个字段分解代码。
【讨论】:
+1 我必须努力学习“代码合同”。我以前从未听说过他们。你能推荐一个适合初学者的好资源吗?另一个重点是您提到的安全问题。我们还没有涉及到。代码合同是否也旨在处理安全问题。如果是这样,那么我仍然不相信需要编写代码来处理每种可能的用户输入类型,而不是使用执行处理程序。谢谢你的回答。【参考方案6】:你两个都做。
在数据库级别创建约束,并在客户端级别检查这些约束。
无论数据如何输入,数据库上的验证确保没有无效数据进入您的数据库。 客户端的验证改善了用户体验。
【讨论】:
我完全同意你的观点。有一个例外。在处理一般情况时,您可以先处理特定情况,然后再处理越来越少的特定情况,然后再处理一般情况。您可以在一个代码块中执行此操作,用户不会知道任何不同。即超出范围的数字。当记录被提交到数据库时,这将产生一个错误,然后您的程序可以接收并作为特定的执行进行处理。与在 UI 后面或在其他地方的某些逻辑中实际编写代码相反,并准确地复制数据库将为您免费做的事情。谢谢你的回答。 有时您需要在客户端和数据库之间建立一个数据访问层,您可以在其中实现对其他业务规则或数据库引擎无法优雅表示的复杂约束的验证。 那么你是说大学里教的例子就是这样,教程的例子。在现实世界中,我们会让 DB 在可能或优雅的情况下处理错误(例如我给出的简单示例),并且只在非常特殊的情况下真正需要时才编程。以上是关于处理输入验证的专业/首选方式是啥的主要内容,如果未能解决你的问题,请参考以下文章
windows7专业版升级windows10专业版入不了域,是啥原因? 都有哪些解决方法?
显示基于 Firebase 身份验证的 DOM 元素的首选方式是啥