ワンタイムトークン処理のジレンマ(通信エラー&CSRF対策を考える)

通信エラー&CSRF対策を考える
ワンタイムトークン処理のジレンマ
セキュリティと使いやすさを両立するには?

2度同じ操作をしたときは処理は1回だけにしたい
  1. リクエストが来る。token発行。クライアントにハッシュを送信し、DBにtokenを保存する
  2. → 次リクエスト時に2度目を無視するようDBのtokenを変更しておく。
  3.  → ブラウザバックで戻って他の選択肢を実行
  4.   → tokenが一致しないためエラー画面になる。セキュリティ上は問題ないがユーザーは使いにくい

メモ)例えば某WEBゲームの場合ブラウザバックで戻っても殆どの処理はきちんと実行される。
レアアイテム入手時のURLをブックマークしておくと、何度でも見ることができる。
ただし、実際にアイテムを入手するのは1個だけである。


回避方法
1)各リンクごとにtokenを作成&設定しておく → 処理が終わったところからクリアしておく
 問題点)リンクが大量にあるところでは膨大なtokenが必要になる
 → 更新リンク、かつtokenが必要なところのみでOKなので、それほどの量にはならない。


2)各リンクには処理前と処理結果を内包しておく
 → インクリメンタルな処理(他人と共有しているポイントの登録等)の場合、1度目は処理を行い、
  2度目以降は現在値を表示する。
 → 固定的な処理(自分のポイントが50→60になった、等)の場合、リンク内の結果を表示する。
  2度目かどうかは現在ポイントで判断できるので、tokenは不要である。
  ※この例では50ポイントのときに同じURLに来ると増やせてしまうので注意。
   実際にはユーザーに見えない値等を組み合わせて行う。組み合わせがない時はtokenを使う。




@まとめ
  1. 何でもかんでもワンタイムトークン発行しちゃうと使いにくいアプリになるので気をつける。
  2. リンクには処理前と処理結果を内包しておく。
  3. インクリメンタルな処理の時はリンクにワンタイムトークンを設定。
  4. ※ワンタイムトークンがないところでは結果から次ページを生成する。
    ※ワンタイムトークンがあるところでは1度目のみ処理を行い、現在値を表示する。