We all know the good old "disable the submit button" trick but what are the best ways to handle multiple submissions server side? I have an application where it is absolutely critical that a form only be sent once - it processes a credit card. I didn't write how it is right now but as a quick fix I threw on the disable-on-submit technique, however some impatient users that have javascript disabled are still getting charged twice.
我们都知道旧的“禁用提交按钮”技巧,但处理多个提交服务器端的最佳方法是什么?我有一个应用程序,一个表单只发送一次绝对至关重要 - 它处理一张信用卡。我没有写出它现在的情况,但作为一个快速解决方案我投入了禁用提交技术,但是一些不耐烦的用户已经被禁用了两次。
So, what are ways to avoid this? I can think of a few - I have used a few in the past - but I'd like to see if there's any "best practices" on how to tackle this one. I am using PHP but I'm more interested in concepts.
那么,有什么方法可以避免这种情况呢?我可以想到一些 - 我过去曾经使用过一些 - 但我想看看是否有任何关于如何解决这个问题的“最佳实践”。我正在使用PHP,但我对概念更感兴趣。
edit: I am aware of the token technique and it is what I have used in the past, this question is more or less to see if my approach is in line with what the rest of you fine programmers use.
编辑:我知道令牌技术,这是我过去使用的,这个问题或多或少是为了看看我的方法是否与其他优秀程序员使用的方法一致。
6 个解决方案
#1
27
One really effective way is to submit a token along with the request, and keep a list of used tokens. If the token is not valid, or the token has already been processed, then abort.
一种非常有效的方法是提交令牌和请求,并保留使用过的令牌列表。如果令牌无效,或者令牌已被处理,则中止。
The token can be as simple as an incrementing integer, stored in a hidden text field, or you can encrypt it to increase security. This feature can be made more robust by generating the token when the page is created, encrypting it, then confirming the token has been generated AND has not been processed.
令牌可以像递增整数一样简单,存储在隐藏文本字段中,也可以对其进行加密以提高安全性。通过在创建页面时生成令牌,加密它,然后确认令牌已生成且尚未处理,可以使此功能更加健壮。
#2
9
Include a random unique token in a hidden form field. Then on the backend, you can check if it's been submitted before.
在隐藏的表单字段中包含随机唯一标记。然后在后端,您可以检查之前是否已提交。
This is a generally good idea because it helps you defend against XSS attacks as well.
这通常是一个好主意,因为它也可以帮助您抵御XSS攻击。
#3
7
You might also simply test whether an identical transaction has been made in the last minute (or second, depending on the latency of your server). Most people do not buy two identical books (or whatever) within a minute of each other using the same card. If you keep a cache of credit card payments in the last minute and check whether the one you're about to make is identical (same card number, same amount) to one you've just done, chances are you'll spot the duplicate.
您也可以简单地测试是否在最后一分钟(或第二,取决于服务器的延迟)进行了相同的事务。大多数人不会在一分钟之内使用相同的卡购买两本相同的书(或其他)。如果您在最后一刻保留信用卡付款的缓存,并检查您即将制作的信用卡是否与您刚刚完成的信用卡支付相同(卡号相同,金额相同),您可能会发现重复信息。
#4
3
I wouldn't rely on anything client side for this. Why not generate a unique ID for this transaction server-side before presenting the client with the submit button? The client then has to submit this token back, and you check server side that every token is submitted once.
我不会依赖任何客户端。在向客户端提交提交按钮之前,为什么不为此事务服务器端生成唯一ID?然后客户端必须提交此令牌,并检查服务器端是否每次提交一个令牌。
The token can, as other people said, can be an incrementing integer (+ username), or a GUID.
正如其他人所说,令牌可以是递增整数(+用户名)或GUID。
#5
0
I am having a similar problem. After reading this, I am thinking a token might be the way to go. This post shows a good example of implementation.
我有个类似的问题。读完之后,我在想一个令牌可能是要走的路。这篇文章展示了一个很好的实施例子。
#6
-3
No need to generate unique tokens and all that jazz. After form validation passes, simply redirect the visitor to another page that says something like "Your credit card is being processed". If the visitor reloads the page they are reloading the redirected page, not the POST submission.
无需生成独特的令牌和所有爵士乐。表单验证通过后,只需将访问者重定向到另一个页面,上面写着“您的信用卡正在处理”。如果访问者重新加载页面,则他们正在重新加载重定向的页面,而不是POST提交。
#1
27
One really effective way is to submit a token along with the request, and keep a list of used tokens. If the token is not valid, or the token has already been processed, then abort.
一种非常有效的方法是提交令牌和请求,并保留使用过的令牌列表。如果令牌无效,或者令牌已被处理,则中止。
The token can be as simple as an incrementing integer, stored in a hidden text field, or you can encrypt it to increase security. This feature can be made more robust by generating the token when the page is created, encrypting it, then confirming the token has been generated AND has not been processed.
令牌可以像递增整数一样简单,存储在隐藏文本字段中,也可以对其进行加密以提高安全性。通过在创建页面时生成令牌,加密它,然后确认令牌已生成且尚未处理,可以使此功能更加健壮。
#2
9
Include a random unique token in a hidden form field. Then on the backend, you can check if it's been submitted before.
在隐藏的表单字段中包含随机唯一标记。然后在后端,您可以检查之前是否已提交。
This is a generally good idea because it helps you defend against XSS attacks as well.
这通常是一个好主意,因为它也可以帮助您抵御XSS攻击。
#3
7
You might also simply test whether an identical transaction has been made in the last minute (or second, depending on the latency of your server). Most people do not buy two identical books (or whatever) within a minute of each other using the same card. If you keep a cache of credit card payments in the last minute and check whether the one you're about to make is identical (same card number, same amount) to one you've just done, chances are you'll spot the duplicate.
您也可以简单地测试是否在最后一分钟(或第二,取决于服务器的延迟)进行了相同的事务。大多数人不会在一分钟之内使用相同的卡购买两本相同的书(或其他)。如果您在最后一刻保留信用卡付款的缓存,并检查您即将制作的信用卡是否与您刚刚完成的信用卡支付相同(卡号相同,金额相同),您可能会发现重复信息。
#4
3
I wouldn't rely on anything client side for this. Why not generate a unique ID for this transaction server-side before presenting the client with the submit button? The client then has to submit this token back, and you check server side that every token is submitted once.
我不会依赖任何客户端。在向客户端提交提交按钮之前,为什么不为此事务服务器端生成唯一ID?然后客户端必须提交此令牌,并检查服务器端是否每次提交一个令牌。
The token can, as other people said, can be an incrementing integer (+ username), or a GUID.
正如其他人所说,令牌可以是递增整数(+用户名)或GUID。
#5
0
I am having a similar problem. After reading this, I am thinking a token might be the way to go. This post shows a good example of implementation.
我有个类似的问题。读完之后,我在想一个令牌可能是要走的路。这篇文章展示了一个很好的实施例子。
#6
-3
No need to generate unique tokens and all that jazz. After form validation passes, simply redirect the visitor to another page that says something like "Your credit card is being processed". If the visitor reloads the page they are reloading the redirected page, not the POST submission.
无需生成独特的令牌和所有爵士乐。表单验证通过后,只需将访问者重定向到另一个页面,上面写着“您的信用卡正在处理”。如果访问者重新加载页面,则他们正在重新加载重定向的页面,而不是POST提交。