二重サブミット対策とか

qiita.com

バズっていたので個人的感想。
コメントつけようかと思っていたが、第三者的には有効な情報ではない気もしたので、ここで。

記事の内容

二重サブミットが発生する状況

  1. サブミットボタンをダブルクリックする
  2. 戻るボタンで戻って、再度保存ボタンを押す
  3. 完了ページでブラウザリロードする
  4. CSRF攻撃による不正な更新リクエスト

対策

  1. トークンによるチェック
  2. JavaScriptでのサブミットボタンのDisable化
  3. PRGパターン

でもって、

ここから個人的な感想。

そもそも二重サブミット対策をするか?

単純な問い合わせフォームやアンケートフォーム等については、PRGパターンのみ採用し(完了画面リロードによる登録防止)、他はしないかもしれない。
同一人物の複数登録チェックが必要な場合、どのみちそれはデータクリーニング時に必須な工程となるから。

そう考えると、「トークンによるチェック」等は認証前提の会員系サイトへの対応で限定される気がする。

「トークンによるチェック」

CSRF対策としては、最近この手法を使うことが多い(自分の記事)。

qiita.com

ただ、この場合、1ページ1トークンの為、「戻るボタン」の処理が行えない。
(CSRFチェックのエラーとなる)

「戻るボタン」を有効にするか?

入力ー確認ー完了でトークンを同じにすることで、戻るボタンで画面を戻ってリクエストを再送信しても、完了画面以外はエラーにならず(!)、ユーザビリティが確保されます。
例えば、確認画面に「入力画面へ戻る」ボタンをつけなくても、ブラウザの戻るボタンで遷移することができ、トークンエラーにもなりません!

 ユーザビリティが落ちるのは承知だが、「確認ページから入力ページへの遷移の為の戻るボタン動作は保証しません」と言い切ることが多い。

  • 動作ブラウザや状況によって、キャッシュの扱い状況がバラバラ過ぎて、サーバサイドで管理するのが難しい。
  • 「入力エラー発生時ページ」も合わせて考える必要がある。
  • JavaScriptによる動的な画面更新や入力値補完が行われていた場合、それが全て残っているとは限らない。

もし対応する場合、最近であれば、pushState機構を用いて遷移を制御するのが正道なのかな、と思う。

「入力」=>「確認」=>「完了」について

そもそも「確認ページが必須」というのが割と日本的文化の為、多くのフレームワーク自体はその機能を持っていないのでは?とは思っている。

(項目数の関係で)入力画面が複数にわたる場合、文化に関わらず、確認画面は必要になると思うのだが、それはそれで一般化しにくい仕様なので、標準機能としては備えてないのだろう。

JavaScriptでのサブミットボタンのDisable化」

古いWEBアプリケーションの場合、Disable化対応が原因で誤動作を起こしているものがたまにあるので、個人的にイメージがあまり良くないが、

ただ、回線が遅く遷移前にブラウザの停止ボタンを押した場合は、ボタンを二度と押せなくなってしまうため、↑の方式に一定時間でボタンをenabledにするようにした方が親切です。

ダブルクリック対策の参考として良いかも。

「PRGパターン」

リダイレクトさせる方法は知っていたが、パターン名がついているのは知らなかった。