在一处管理客户端和服务器端验证


17

我在船上100%与1的情况应该 肯定使用了客户端和服务器端的数据验证。

但是,在我工作过的框架和环境中,我见过的方法从来都不是DRY。大多数情况下,没有计划或模式-验证写在模型规范中,而验证则写在视图上的表单中。(注意:我大部分的第一手经验是使用Rails,Sinatra和带有jQuery的PHP)

考虑一下,创建一个生成器似乎并不困难,只要生成一组验证(例如,模型名称,字段,条件),就可以生成必要的客户端和服务器端材料。或者,这种工具可以接受服务器端验证(例如validatesActiveRecord模型中的代码),并生成客户端验证(例如jQuery插件),然后将其应用于表单。

显然,以上只是“嘿,我有这个主意”,而不是正式的建议。这种事情肯定比这个主意击中时看起来要困难得多。

这使我想到一个问题:您将如何设计一种“一次写入,在服务器和客户端上运行”的数据验证技术?

相关子主题:是否存在针对任何特定框架或客户端服务器技术的类似工具?尝试仅维护一组验证有哪些主要难题或挑战?

Answers:


6

以我有限的经验,需要验证的地方是

  1. 使用HTML的展示级别,
  2. 在演示后级别(即Java验证),
  3. 在必须一起验证多个字段之间的交互的组合级别,
  4. 在业务逻辑级别
  5. 在数据库级别。

它们每个都有不同的语言,时间和触发器。例如,除非整个记录都处于一致状态,否则验证字段几乎没有意义,除非您只想验证一条记录。数据库级别的约束只应在提交之前结束时才适用,并且不能轻易地逐段完成。

一个相关的概念是表示数据在每个级别之间有所不同。一个简单的例子是,Web浏览器将一段文本表示为CP1290,而数据库则以UTF-8表示。两个字符串的长度不同,因此强制长度约束变得很尴尬。


是的,不同的语言和框架使其不切实际。这不是“不可撤销的”,因为可以完成足够的资源,但是在语言之间或之间编写自动转换器是一项巨大的任务。在合理的时间范围内进行操作,然后在相关技术发生变化时对其进行维护将是很多工作。
Michael Durrant 2014年

确实可以在浏览器中执行许多服务器端验证(例如,字段的唯一性)。但是,也确实需要在服务器中重复进行任何客户端验证,因为您不能信任客户端。那就是我看到的将事情变干特别有用的地方。例如,我可以看到一个扩展Rails form_for来自动提供客户端验证代码的工具非常有用。
Dan

5

通常限制解决方案的一个考虑因素是网络往返。客户端应该在不通过网络发送消息的情况下验证用户数据。换句话说,当用户单击“提交”按钮时,客户端应在本地验证数据。

首先,假设我们没有此限制。我们可以与擅长阐明验证问题的网络端点进行通信。例如,当您向其提交新的User记录时,而不是使用普通的HTTP错误代码进行响应,它可能会返回详细的JSON响应,逐项列出问题,客户端将巧妙地更新显示内容以反映遇到的问题。端点扮演验证网关的角色。

它很干,但并非没有缺点。首先,它取决于网络往返,向我们的服务器收取可能由客户端处理的验证费用。其次,设计预期所有CRUD操作都将通过我们的端点进行,但是当开发人员和流程直接针对数据库绕过我们的数据访问层时,又该怎么办?

让我们重新审视解决这些缺点的解决方案。相反,让我们以元数据的形式存储和传递验证信息:

{field: 'username', type: 'required'}
{field: 'username', type: 'unique'} //requires a network roundtrip
{field: 'password', type: 'length', min: 10, max: 50}
{field: 'password', type: 'contains', characters: ['upper', 'special', 'letter', 'number']}

客户端和服务器都将具有某种机制(例如引擎)来解释和应用此数据。(有人称它为免费的monad,因为它将声明性部分与解释器分开了。)在JavaScript中,我们可以将每条信息映射到工作函数。要启动,我们可以教我们架构的任何层,包括我们的数据库,以一致地执行验证。


当一个字段在Web浏览器,传输,实现语言和数据库中以不同的方式表示时,您如何描述一个字段?例如,使用CP1290(IE),UTF-8(JSON),UTF-8(C#)或UCS-16(Oracle)时,表示字符串字段所需的字节数会有所不同。长度约束是什么意思?对于浏览器而言更重要的是,何时字符表示取决于浏览器和操作系统?
BobDalgleish 2014年

这些约束旨在作为人类的心理模型。作为程序员的工作是将差异提取到计算机中,以便该人员不必关心任何技术差异。
Mario T. Lanza 2014年

您完全错了。到目前为止,还没有人提出一种允许使用一个规范进行端到端验证的抽象。在OP中,“只写一次”意味着具有解决不同阶段的不同子句不符合条件。同样,在您提出的验证中没有发现解决场间或对象间验证的问题。
BobDalgleish 2014年

场间/对象验证并不是一件容易的事。元数据仅表示关系。一次写入意味着我一次写入一次验证,并在多个站点上强制执行此操作。您将元数据添加到表中。该元数据可被任何站点接收,并且简单的类/实用程序/引擎会强制执行约束。
Mario T. Lanza 2014年

1
这种验证语言将非常有用。它可能会取代与UI密集型Web应用程序有关的代码的三分之一。
BobDalgleish 2014年

2

一种方法是在服务器端和客户端使用相同的语言/框架。

例如

Node.js :: JavaScript中的客户端/服务器GET :: Java中的客户端/服务器

在这种情况下,大多数“域对象”代码都是通用的,其中包括验证。框架将根据需要调用代码。例如,在“提交”之前和服务器端Web服务中,将在浏览器中调用相同的代码。

编辑(2014年6月):现在,借助Java 8,也很容易将JS验证代码集成到Java应用程序中。Java 8有一个新的JS执行引擎,该引擎更永久(例如:它使用invokeDynamic)。


当涉及到SQL数据库时,不确定如何运行。
Michael Durrant 2014年

它也不能解决浏览器和操作系统影响输入域的问题。
BobDalgleish 2014年

@Micheal Durrant,用于数据库验证被实现为数据库约束(例如外键,唯一性等)。BobDalgleish,1.通过使用根据浏览器(例如Sencha)调整运行时的库,可以减轻浏览器/操作系统兼容性的问题。2.浏览器的兼容性通常不会影响代码的“逻辑”部分,例如验证,兼容性问题通常是DOM / UI渲染。
Shamit Verma 2014年

0

我只是在想同样的问题。我正在考虑使用ANTLR在C#和javascript中获取抽象语法树。在这里,您可以使用树浏览器将语言指定的操作应用于要验证的对象。

因此,您可以在任何需要的地方(可能在数据库中)存储所需验证的描述。

这就是我要解决的问题。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.