PHP:按下“后退”键时阻止表单被意外重新处理
当用户点击“后退”按钮时阻止表单被重新处理的最佳方法是什么?
我遵循 Post/Redirect/Get 模式,所以我不如果按 F5 不会有问题,但后退按钮仍然提供重新提交表单的机会。如果此表单是信用卡处理页面,那就不好了。
这个问题已经被问到这里,但措辞和答案质量很差,并且不完全针对这个问题。
我有 form.php 提交给自己。如果提交时输入数据没有错误,用户将被重定向到 form_thanks.php。回击(和“发送”或“重新提交”)一次会重新提交 form.php(糟糕!),然后将它们带回 form_thanks.php。
如果可能的话,还请包括不涉及使用会话的解决方案。
What is the best way to stop a form from being reprocessed when a user hits a Back button?
I'm following the Post/Redirect/Get pattern, so I don't have a problem if F5 is pushed, but the back button still provides the opportunity to resubmit the form. If this form is a credit card processing page, this is bad.
This question has been asked somewhat here, but the phrasing and answers were of poor quality and not specific to this problem exactly.
I have form.php which submits to itself. If there were no errors in input data upon submission, the user is redirected to form_thanks.php. Hitting back (and "Send" or "Resubmit") once resubmits form.php (BAD!) and then brings them back to form_thanks.php.
Please also include solutions that do not involve using Sessions, if possible.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
我会用不同的方式来做。使用随机字符串作为值放置隐藏输入,并在提交时将该随机字符串存储在会话中。设置一个简单的检查,看看他们是否已经发布,以及是否不接受输入。
I would do it a different way. Put up a hidden input with a random string as the value, and when it's submitted store that random string in a session. Set up a simple check to see if they've already posted it and if they have don't accept the input.
这应该使用一次性令牌或 nonce 来完成。 php/server 应该在隐藏的表单字段中包含此令牌。
它应该存储所有最近令牌的列表,并且每次提交表单时,它应该检查该令牌是否在最近有效令牌的列表中。
如果它不在列表中,则不要重新处理该表单。
如果它在列表中,则处理该表单并从列表中删除该令牌。
令牌可以在会话中处理,也可以在没有会话的情况下仅在简单的数据库表中处理。不过,令牌应该是特定于用户的。
这也是避免 CSRF 攻击的推荐方法。
This should be done with a single-use token, or a nonce. The php/server should include this token in a hidden form field.
It should store a list of all the recent tokens and each time a form is submitted, it should check to see if the token is in the list of recent valid tokens.
If it's not in the list, then don't reprocess the form.
If it is in the list, then process the form and remove the token from the list.
The tokens can be handled within sessions or just a simple database table without sessions. The tokens should be user-specific though.
This is also the recommended way to avoid CSRF attacks.
只是在这里大声思考。但是 post/redirect/get 的变体怎么样,其中最终的 get 实际上并不是最终的 get ;) 相反,它反过来总是自动转发到真正的最终页面,这样如果用户点击后退按钮,他们就会返回他们从哪里来的?
编辑:
好的,考虑到OP的评论,这是另一个想法。表单提交的 URL 可以要求一个仅适合一种用途的参数。该令牌将在提交表单之前生成(使用 MD5 或类似方法),并且可以存储在数据库中(响应其他人的建议,您请求了不使用会话的解决方案)。处理表单后,该令牌将在数据库中标记为已使用。这样,当使用相同的令牌返回页面时,可以采取措施防止向后端重新提交表单数据。
Just thinking out loud here. But what about a variation on post/redirect/get where the final get is not actually the final get ;) But rather, it in turn always automatically forwards to the truly final page, so that should the user hit the back button, they return right back whence they came?
EDIT:
Ok, taking into consideration the OP's comment, here's another idea. The URL for the form submission could be made to require a parameter that is good for only one use. That token would be generated (using MD5 or some such) before the form was submitted and could be stored in a database (in response to somebody else's suggestion you requested a solution without using sessions). After the form is processed, this token would then be flagged in the database as having already been used. So that when the page is returned to with the same token, steps can be taken to prevent the resubmission of the form data to the backend.
迟到的答复,但可以通过使用基于 AJAX 的解决方案完全避免处理;在此处理方案中包含随机数不会有问题,但通过使用异步查询(成功后会重定向用户),不会通过刷新、按回车或单击按钮以外的任何方式重复请求。
通过嵌入请求的处理程序(无论是使用 PrototypeJS 或 jQuery 的高级别还是使用您的低级别),还可以轻松实现一种机制,防止按钮被按下两次或在请求期间发生某些情况时被“锁定”。 handrolled 函数)分别在请求完成和首次触发时启用和禁用按钮的机制。
Late answer, but one could avoid the processing altogether by using an AJAX-based solution; there wouldn't be an issue with including a nonce with this processing scheme, but by using an asynchronous query which, on success, redirects the user, the requests are not repeated by refreshing, pressing back, or anything other than clicking the button.
It is also easy to implement a mechanism that prevents the button from either being pressed twice or being "locked up" if something happened during the request by embedding into the handler for the request (whether high level with PrototypeJS or jQuery or low level with your handrolled function) the mechanisms to enable and disable the button when the request completes and first fires, respectively.
我发现 back 会将表单恢复到页面重定向之前的状态,如果是这种情况,有一个隐藏的输入/变量或以 true 开头的值,然后一旦提交表单,并且如果value为true,修改为false然后提交,否则返回false
I find that back will bring the form to the state it was before the page was redirected, if that is the case, have a hidden input/variable or something which starts with value say true, then once the form is submitted, and if the value is true, change it to false and then submit, else return false
试试这个:
Try this :