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

JavaScript: client-side vs. server-side validation

提问人:Brad8118 提问时间:10/2/2008 最后编辑:Yi JiangBrad8118 更新时间:8/24/2021 访问量:154374

问:

客户端和服务器端验证哪个更好?

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

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

我所做的很多验证都是在用户输入数据时对其进行验证。 例如,我使用该事件来防止文本框中的字母,设置最大字符数,并且数字在范围内。keypress

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


真棒回答大家。我们拥有的网站受密码保护,用户群很小(<50)。如果他们没有运行 JavaScript,我们将派出忍者。但是,如果我们为每个人设计一个网站,我会同意对双方都进行验证。

JavaScript 安全 验证

评论

3赞 Enrico Murru 10/2/2008
可以禁用 JavaScript
0赞 Stewart 11/15/2019
没有确定的方法可以阻止禁用 JavaScript 的用户。如果用户在启用 JS 的情况下访问您的页面,然后禁用它,则您无能为力。 (好的,您可以使用 JS 来实现提交控件,以便它在这种情况下停止工作,但这可以像其他所有内容一样被绕过。

答:

86赞 Vinko Vrsalovic 10/2/2008 #1

是的,客户端验证始终可以完全绕过。您需要同时执行这两个操作,客户端以提供更好的用户体验,服务器端需要确保您获得的输入实际上经过验证,而不仅仅是客户端验证。

-3赞 Tom 10/2/2008 #2

如果您正在进行轻量级验证,最好在客户端上进行。它将节省网络流量,从而帮助您的服务器更好地运行。如果涉及从数据库或其他东西(如密码)中提取数据的验证变得复杂,那么最好在可以安全检查数据的服务器上进行。

评论

2赞 kremuwa 9/18/2015
你所崇拜的不是最好的主意。用户始终可以绕过客户端验证,并将他们想要的任何内容提交到数据库。
34赞 Rob 10/2/2008 #3

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

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

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

19赞 Peter Boughton 10/2/2008 #4

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

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

46赞 Toby Hede 10/2/2008 #5

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

始终在服务器上进行验证

并添加 JavaScript 以提高用户响应能力。

388赞 Nathan Long 10/2/2008 #6

正如其他人所说,你应该两者兼而有之。原因如下:

客户端

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

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

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

服务器端

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

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

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

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

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

附录 - 2016年12月

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

评论

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

好吧,我仍然有一些回答的余地。

除了 Rob 和 Nathan 的回答之外,我还要补充一点,进行客户端验证很重要。在 Web 表单上应用验证时,必须遵循以下准则:

客户端

  1. 必须使用客户端验证才能筛选来自您网站上真实用户的真实请求。
  2. 应使用客户端验证来减少服务器端处理期间可能发生的错误。
  3. 应使用客户端验证来最大程度地减少服务器端往返,从而节省带宽和每个用户的请求数。

服务器端

  1. 您不应该假设在客户端成功完成的验证是 100% 完美的。即使它服务的用户少于 50 个。你永远不知道你的哪个用户/员工会变成一个“邪恶”,并做一些有害的活动,因为你知道你没有适当的验证。
  2. 即使它在验证电子邮件地址、电话号码或检查一些有效输入方面是完美的,它也可能包含非常有害的数据。无论正确还是不正确,都需要在服务器端进行过滤。
  3. 如果绕过客户端验证,则服务器端验证将帮助您避免对服务器端处理的任何潜在损害。最近,我们已经听到了很多关于SQL注入和其他类型的技术的故事,这些技术可能被应用以获得一些邪恶的好处。

这两种类型的验证在各自的范围内都发挥着重要作用,但最强大的是服务器端。如果您在单个时间点收到 10k 用户,那么您肯定会最终过滤到您的 Web 服务器的请求数量。如果您发现有一个错误,例如无效的电子邮件地址,那么他们会再次发回表单并要求您的用户更正它,这肯定会占用您的服务器资源和带宽。因此,最好应用 javascript 验证。如果 javascript 被禁用,那么您的服务器端验证将派上用场,我敢打赌,只有少数用户可能不小心禁用了它,因为 99.99% 的网站使用 javascript,并且它已经在所有现代浏览器中默认启用。

评论

0赞 Stewart 11/15/2019
我见过人们完全忽略了对代码注入的保护,更不用说只在客户端这样做了。如果没有指向以下内容的链接,对代码注入的引用是不完整的:xkcd.com/327:)
9赞 Jonathan 4/28/2013 #8

您可以执行服务器端验证并发回一个 JSON 对象,其中包含每个字段的验证结果,将客户端 Javascript 保持在最低限度(仅显示结果),并且仍然具有用户友好的体验,而无需在客户端和服务器上重复自己。

评论

3赞 quadrupleslap 2/13/2017
用户友好?或。几乎是瞬间和黄油般的光滑?可能不是。
4赞 adardesign 8/1/2013 #9

客户端应通过 HTML5 输入类型模式属性使用基本验证,因为这些属性仅用于渐进式增强以获得更好的用户体验(即使 <IE9 和 safari 不支持它们,但我们不依赖它们)。但主要的验证应该发生在服务器端。

评论

0赞 Stewart 11/15/2019
“但主要的验证应该在服务器端进行。不应该,必须。
2赞 TaylorMac 10/4/2013 #10

JavaScript 可以在运行时修改。

我建议在服务器上创建验证结构并与客户端共享的模式。

您需要在两端使用单独的验证逻辑,例如:

"required"客户端上的属性inputs

field.length > 0服务器端。

但是,使用相同的验证规范将消除两端镜像验证的一些冗余(和错误)。

4赞 gaurav vashisht 11/13/2013 #11

我建议同时实施客户端和服务器验证,以使项目更加安全......如果我必须选择一个,我将进行服务器端验证。

您可以在此处找到一些相关信息 https://web.archive.org/web/20131210085944/http://www.webexpertlabs.com/server-side-form-validation-using-regular-expression/

3赞 roland 11/20/2015 #12

我遇到了一个有趣的链接,它区分了严重的、系统的、随机的错误。

Client-Side validation非常适合防止严重和随机错误。通常为任何输入的最大长度。不要模仿服务器端验证规则;提供您自己的粗略经验法则验证规则(例如,客户端为 200 个字符;服务器端的特定字符少于 200 个字符,由强业务规则决定)。n

Server-side validation非常适合防止系统误差;它将强制执行业务规则。

在我参与的一个项目中,验证是通过 ajax 请求在服务器上完成的。在客户端上,我相应地显示错误消息。

延伸阅读:大误差、系统误差、随机误差:

https://answers.yahoo.com/question/index?qid=20080918203131AAEt6GO

2赞 Billal Begueradj 4/24/2019 #13

客户端数据验证对于更好的用户体验很有用:例如,我一个输入错误电子邮件地址的用户,不应该等到远程服务器处理他的请求时才知道他所做的错别字。

然而,由于攻击者可以绕过客户端验证(甚至可能根本不使用浏览器),因此服务器端验证是必需的,并且必须是保护您的后端免受恶意用户攻击的真正大门。