最初に自問しなければならない質問は、次のとおりです。回避したい問題のシナリオはどのようなものですか?
- ユーザーが誤って (またはイライラして ...) ボタンを 2 回クリックした。
- 1 回しか利用できないリソース (飛行機の特定の座席の予約など) が 2 回消費されること。
「どちらも避けたい」とだけ言わないでください。その場合でも、2 つの問題を別々に処理する必要があります。
問題1
これは、クライアント側でより適切に解決されます (たとえば、クリックされたボタンを無効にするなど)。
サーバー側でも解決できますが(シーケンス番号やトークン、またはコンテンツのハッシュコードをチェックすることで...)、ポイントがわかりません。ユーザーが本当に 2 回送信したい場合 (たとえば、ボタンが無効にならないように JavaScript を操作するなど) は、許可してください。問題 1 はセキュリティに関するものではありません。
問題 2
これは (非常に特殊な状況を除いて) サーバー側で解決する必要があります。主にセキュリティについてです。しかし、考えてみると、この問題は二重送信防止では解決できません! なぜだめですか?
例を見てみましょう: 飛行機の座席は 1 回だけ予約する必要があります。これは、複数の方法で違反される可能性があります。
- 二重提出によって。
- 同じユーザーが同時に別のブラウザ ウィンドウから送信するなど。
- 複数のユーザーが同時に予約しようとした場合。
この問題を解決するクリーンな方法は、座席を予約してアトミックに座席の空室状況を確認することです。違反が二重送信によって引き起こされた場合、それは実際には問題ではありません (偶発的な二重送信は問題 1 でカバーされます)。
...そして問題3
自動再送信メカニズムを実装している場合は、第 3 の種類の問題も発生する可能性があります。
ユーザーが自分のショッピング カートに商品を追加したいとします。クライアントが送信し、タイムアウト前にサーバーからの応答を受信しません。そのため、自動的に再送信されます。ただし、サーバーは両方のメッセージを受信し、両方を処理しようとします。そのため、アイテムがショッピング カートに 2 回追加されます。
私の意見では、これを回避するための最善の解決策は、通常、「カートに 1 つのアイテムを追加する」などのアクションを使用するのではなく、「アイテムの目標数を 1 に設定する」ことです。繰り返しますが、シーケンス番号などを操作することもできます。