JavaScript:客户端与服务器端验证

IT技术 javascript security validation
2021-01-22 04:31:50

哪个更好地进行客户端或服务器端验证?

在我们的情况下,我们正在使用

  • jQuery 和 MVC。
  • 在我们的视图和控制器之间传递的 JSON 数据。

我所做的很多验证都是在用户输入数据时验证数据。例如,我使用该keypress事件来防止文本框中出现字母,设置最大字符数以及一个数字在一个范围内。

我想更好的问题是,在客户端进行服务器端验证有什么好处吗?


各位大大回答一下。我们拥有的网站受密码保护,适用于小型用户群(<50)。如果他们没有运行 JavaScript,我们将发送 ninjas。但是,如果我们为每个人设计一个站点,我会同意在双方进行验证。

6个回答

正如其他人所说,你应该两者都做。原因如下:

客户端

您希望首先在客户端验证输入,因为您可以向普通用户提供更好的反馈例如,如果他们输入无效的电子邮件地址并移至下一个字段,您可以立即显示错误消息。这样用户就可以提交表单之前更正每个字段

如果您仅在服务器上进行验证,则他们必须提交表单、收到错误消息并尝试查找问题。

(这种痛苦可以通过让服务器在填写用户原始输入的情况下重新呈现表单来缓解,但客户端验证仍然更快。)

服务器端

您希望在服务器端进行验证,因为您可以防范恶意用户,他们可以轻松绕过您的 JavaScript 并向服务器提交危险输入。

信任你的用户界面是非常危险的。他们不仅会滥用您的用户界面,而且他们可能根本不会使用您的用户界面,甚至可能不会使用浏览器如果用户手动编辑 URL,或者运行他们自己的 Javascript,或者使用其他工具调整他们的 HTTP 请求怎么办?例如,如果他们curl从脚本或从脚本发送自定义 HTTP 请求会怎样?

这不是理论上的;例如,我在一个旅行搜索引擎上工作,该引擎通过发送POST请求将用户的搜索重新提交给许多合作航空公司、巴士公司等,就像用户填写了每个公司的搜索表单一样,然后收集和排序所有的结果。那些公司的表单 JS 从来没有被执行过,他们在返回的 HTML 中提供错误消息对我们来说至关重要。当然,一个 API 会很好,但这是我们必须做的。

不允许这样做不仅从安全角度来看是幼稚的,而且也是非标准的:应该允许客户端通过他们希望的任何方式发送 HTTP,并且您应该正确响应。这包括验证。

服务器端验证对于兼容性也很重要- 并非所有用户,即使他们使用浏览器,都会启用 JavaScript。

附录 - 2016 年 12 月

有些验证甚至无法在服务器端应用程序代码中正确完成,而在客户端代码中则完全不可能,因为它们取决于数据库的当前状态。例如,“没有其他人注册过那个用户名”,或者“你评论的博客文章仍然存在”,或者“没有现有的预订与你请求的日期重叠”,或者“你的账户余额仍然足以支付这次购买的费用” .” 只有数据库才能可靠地验证依赖于相关数据的数据。开发人员经常搞砸,但PostgreSQL 提供了一些很好的解决方案

@kidmosey“这明显违反了 DRY 原则”是的,这对我们这样的程序员来说意味着痛苦。但是想象一个注册表单。如果在客户端代码中复制“电子邮件地址必须包含@”的知识意味着用户获得更快的反馈并且更多的人注册,从而每年产生 10 万美元的额外收入,那么它就足以支付额外的维护成本。DRY 是一个很好的原则,但它不是唯一的考虑因素。代码质量的真正衡量标准是它在成本/收益分析中为用户和组织服务的程度。
2021-03-18 04:31:50
@NathanLong 验证对竞争条件敏感的数据并不像这句话听起来那么难。正确地做很痛苦,但是创建一个使用同步资源来请求的保留机制。因此,如果用户键入“usernameA”,则在服务器上进行唯一性检查,不允许多个同时调用以检查是否唯一;如果是唯一的,还保留一个分配给客户端的临时令牌,如果不同的用户名被相同的会话 ID 测试,则该令牌也会被释放。令牌应在合理的时间后过期。示例:TicketMaster 座位预留。
2021-03-19 04:31:50
@ArunRaaj 是的,您会通过这种方式解决大部分问题,但并非 100% 可靠。如果两个用户同时填写表单,他们可能会被告知这user1是一个可用的用户名。当他们提交时,除非您重新检查服务器端,否则他们将获得相同的用户名。甚至在服务器应用程序代码中检查也可能有同样的问题:两个请求进来,第一个检查数据库并被告知 OK,第二个检查数据库并被告知 OK,第一个被保存,第二个被保存作为副本。只有 db 唯一约束才能保证唯一性。
2021-03-20 04:31:50
内森,我刚读了你 2016 年的编辑。并且您正确地指出了要从数据库完成的验证。但是您知道数据库验证实际上是在服务器端验证下进行的,您可以在其中检查用户名(如果可用)。
2021-04-03 04:31:50
@KMX 我试图将可靠的东西(例如 db 唯一约束)与不可靠的东西区分开来,例如让服务器端应用程序代码执行 aSELECT后跟 an INSERT,这意味着有可能INSERT在两者之间完成另一个锁定表可以防止这种情况发生,但唯一约束要好得多。
2021-04-05 04:31:50

是的,客户端验证总是可以完全绕过的。您需要同时执行客户端以提供更好的用户体验和服务器端以确保您获得的输入实际经过验证,而不仅仅是由客户端进行验证。

我只是要重复一遍,因为它非常重要:

始终在服务器上验证

并为用户响应添加 JavaScript。

与客户端验证相比,进行服务器端验证的好处是可以绕过/操纵客户端验证:

  • 最终用户可以关闭 javascript
  • 数据可以由甚至不使用您网站的人直接发送到您的服务器,而定制的应用程序可以这样做
  • 您页面上的 Javascript 错误(由多种原因引起)可能会导致您的部分验证运行,但不是全部

简而言之 - 始终,始终验证服务器端,然后将客户端验证视为增加的“额外”以增强最终用户体验。

必须始终在服务器上进行验证。

在客户端上进行验证对用户来说也很好,但完全不安全。