【问题标题】:JavaScript: client-side vs. server-side validationJavaScript:客户端与服务器端验证
【发布时间】:2010-09-14 19:10:19
【问题描述】:

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

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

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

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

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


真棒回答每个人。我们拥有的网站是受密码保护的,并且用户群很小(

【问题讨论】:

  • 可以禁用javascript
  • 无法阻止禁用 JavaScript 的用户。如果用户在启用 JS 的情况下访问您的页面,然后将其禁用,则您无能为力。 (好吧,你可以使用JS来实现提交控制,这样在这种情况下它就会停止工作,但是这可以像其他任何事情一样被绕过。)

标签: javascript security validation


【解决方案1】:

是的,始终可以完全绕过客户端验证。您需要同时做到这两点,客户端以提供更好的用户体验,服务器端确保您获得的输入经过实际验证,而不仅仅是假设由客户端验证。

【讨论】:

    【解决方案2】:

    如果您要进行光照验证,最好在客户端上进行。它将节省网络流量,这将有助于您的服务器更好地执行。如果验证复杂,涉及从数据库中提取数据或其他内容(如密码),那么最好在可以安全检查数据的服务器上进行。

    【讨论】:

    • 你所追求的并不是最好的主意。用户始终可以绕过客户端验证并将他们想要的任何内容提交到数据库。
    【解决方案3】:

    进行服务器端验证优于客户端验证的好处是可以绕过/操纵客户端验证:

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

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

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

        【解决方案5】:

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

        始终在服务器上验证

        并添加 JavaScript 以实现用户响应。

        【讨论】:

          【解决方案6】:

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

          客户端

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

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

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

          服务器端

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

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

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

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

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

          附录 - 2016 年 12 月

          有些验证甚至无法在服务器端应用程序代码中正确完成,而在客户端代码中则完全不可能,因为它们取决于数据库的当前状态。例如,“没有其他人注册该用户名”,或“您评论的博客文章仍然存在”,或“现有预订没有与您请求的日期重叠”,或“您的帐户余额仍有足够的金额支付该购买。” 只有数据库才能可靠地验证依赖于相关数据的数据。开发者regularly screw this up,但PostgreSQL provides some good solutions

          【讨论】:

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

          嗯,我还是找到了回答的余地。

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

          客户端

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

          服务器端

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

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

          【讨论】:

          • 我看到人们完全忽略了防止代码注入,更别提只在客户端这样做了。如果没有指向此的链接,则对代码注入的引用是不完整的:xkcd.com/327 :)
          【解决方案8】:

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

          【讨论】:

          • 用户友好?可能是。几乎瞬间和黄油般光滑?可能不会。
          【解决方案9】:

          客户端应通过HTML5 input typespattern attributes 使用基本验证,因为它们仅用于渐进增强以获得更好的用户体验(即使它们在

          【讨论】:

          • "但是主要的验证应该发生在服务器端。"不应该,必须。
          【解决方案10】:

          JavaScript 可以在运行时修改。

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

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

          "required" 客户端上的inputs 属性

          field.length > 0 服务器端。

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

          【讨论】:

            【解决方案11】:

            我会建议同时实现客户端和服务器验证,它可以让项目更加安全......如果我必须选择一个,我将使用服务器端验证。

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

            【讨论】:

              【解决方案12】:

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

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

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

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

              进一步阅读:严重的、系统的、随机的错误:

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

              【讨论】:

                【解决方案13】:

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

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

                【讨论】:

                  猜你喜欢
                  • 2020-09-08
                  • 2017-01-26
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多