【问题标题】:Preventing duplicate form submissions in a stateless system防止在无状态系统中重复提交表单
【发布时间】:2017-12-16 00:53:56
【问题描述】:

在 PHP 中工作时,为了避免重复提交表单,我曾经生成某种唯一的 id,将其存储到会话变量中,并在表单中具有 id,所以在提交时我可以比较值,重新生成那时的会话值。我从不认为这是一个很好的解决方案,但我从来没有想到/找到更好的解决方案。

现在,我正在做一个带有 PHP 后端 (Lumen) 的 Angular 前端,我正在努力想一个不涉及我写入数据库的解决方案。除非我误解了什么,否则我不能在 Angular 和 PHP 之间使用会话,对吗?所以这个解决方案行不通。我唯一能想到的另一件事是在数据库中有一个键/对值,但我从来没有完全理解如何防止像意外双击这样的重复,其中会话/数据库可能不会在第二次之前更新它的键提交开始处理。随着我对无状态系统的了解越来越多,感觉会话并不是放置这类东西的最佳场所?

总的来说,我在创建安全的后端系统以避免重复表单方面遇到了麻烦。使用 Angular,我始终可以通过防止单击按钮、触发 API 调用等来防止重复提交,但我也想添加后端保护,我很想听听专家是如何做到的。

【问题讨论】:

  • 为什么需要后端保护来防止重复提交表单?是否发生了对安全至关重要的事情?对我来说,除了简单的客户端检查之外,这似乎不是人们应该真正关心的事情。
  • 恕我直言,我认为这是客户端问题,为什么不只是在点击按钮后禁用它
  • 这些和下面的答案都回答了我的问题:我的心态一直是,不要相信前端。但是在这种情况下,前端/后端不应该关心彼此在做什么。谢谢。
  • @RhoVisions 是的,就是这样。后端和前端不关心对方在做什么,也不应该如此。除此之外,这让一个后端服务于各种前端客户端。现在你有一个网络应用程序(角度)。稍后您可以添加移动应用程序:ionic、swift、java 等等。无论哪种方式,这些客户端都可以以完全相同的方式与您的后端 API 交互,并且由于您的后端并不关心前端在做什么(甚至它是谁),因此添加额外的客户端非常容易.
  • @RhoVisions 欢迎您。是的,你是对的,你永远不应该信任客户端,但是“重复提交表单”不被认为是来自客户端的恶意行为,它只是一个偶然发生的行为,比如点击按钮两次——甚至更多可能是客户打算多次提交相同的数据。您真正应该在后端关心的是诸如泛滥请求和机器人之类的事情。

标签: php laravel angular


【解决方案1】:

在大多数情况下,这应该在前端受到保护。后端保护解决方案取决于您对独特请求的定义。您可以从共同使请求唯一的属性创建复合键。例如。电子邮件 ID、请求 ID 或任何一组请求参数

DB 不会接受重复的键,您可以捕获异常并在前端优雅地处理它。

例如。时事通讯订阅请求申请 - 请求的唯一性由电子邮件地址和时事通讯类型确定

【讨论】:

    【解决方案2】:

    我确信有办法破解它,但我认为简短的回答是你不想破解它。当您转换到分离的后端/前端时,您正在做的一件事就是专门使您的 API 调用无状态。这是一件好事!无状态、缺少会话等可以极大地简化您的后端应用程序。简而言之,无国籍状态是您这样做的一半原因。

    像你习惯的那样防止重复提交绝对是你需要一个有状态的应用程序来做的事情。因此,它现在完全是前端应用程序的工作。

    最好的办法是以全新的方式考虑您的应用程序。您的 PHP 后端处理无状态 REST 请求,因此如果它收到重复提交,这不是 PHP 的问题。在实践中,角度应该没有问题确保不提交重复项(在前端很容易防止它)。您的 PHP 后端确实需要确保它始终返回适当的响应。因此,例如在注册页面上,背靠背的重复注册请求将导致注册成功,然后注册失败,并显示“该电子邮件已存在”(或类似内容)的消息。否则,您的 PHP 后端将不在乎。我仍然可以完成它的工作。客户的工作是确保不会发生重复提交,或者在发生时弄清相互矛盾的答案。

    无状态是 API 调用的理想品质:如果你搞砸了,你的生活会变得更加困难。

    【讨论】:

      【解决方案3】:

      逻辑很简单,只需禁用提交按钮并在表单提交时向用户显示加载器,然后再次启用按钮并在您从第一个 API 获得响应时隐藏加载器,您也可以清空表单字段.现在,如果用户使用相同的详细信息再次提交表单,您可以轻松访问旧保存的数据并比较它们,并可以警告用户字段已提交。

      如果您使用的是 Angular 4 或 2,

      [disabled] , *ngIf 或 [hidden],Observables 会有所帮助

      重置表单 formRef.reset() https://codecraft.tv/courses/angular/forms/submitting-and-resetting/

      和角度 1 ng-disabled、ng-if 和 HTTP 承诺会有所帮助 并用于重置表格 angularjs form reset error

      【讨论】:

        猜你喜欢
        • 2017-03-07
        • 2011-06-04
        • 2016-12-07
        • 2011-02-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多