Hatena::ブログ(Diary)

もやし日記

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';
}
?>

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証