2007-10-21
すごいリロード対策
紹介されているのはシンプルなワンタイムトークン.
単純なリロード対策であれば ticket の値は乱数でなくても良い.ここを乱数にすることで CSRF 対策も兼ねている.ただこの方法は,場合によってはフォームを正常に送信できなくなってしまう問題がある.
例えば,入力画面→入力確認画面と遷移してから別のウィンドウで入力画面→入力確認画面と遷移すると,前の入力確認画面のフォームは ticket が無効になり,フォームを送信できなくなる(複数画面同時編集ができない).
解決策としては,発行したトークンを全て記憶しておき,POST されたトークンと照合する方法がある.
- confirm.php
<?php session_start(); $token = sha1(uniqid(mt_rand(), true)); // トークンをセッションに追加する $_SESSION['token'][] = $token; ?> <form action="complete.php" method="post"> <input type="hidden" name="token" value="<?php echo h($token)?>"> <input type="submit" name="submit_button" value="完了画面へ遷移"> </form>
- complete.php
<?php session_start(); // 送信されたトークンがセッションのトークン配列の中にあるか調べる $key = array_search($_POST['token'], $_SESSION['token']); if ($key !== false) { // 正常な POST unset($_SESSION['token'][$key]); // 使用済みトークンを破棄 echo 'OK'; } else { echo 'invalid token'; } ?>
トラックバック - http://d.hatena.ne.jp/p4life/20071021/1192960112
