[PHP] フォームで、リロードによる再送信を防ぐ(トークン利用)

最終更新:2024/03/29

下記のファイルが同じディレクトリ内にあるものとします。

  • 入力画面:input.php
  • 送信先画面:result.php

入力画面

<?php
session_start();
$token = uniqid('', true);
$_SESSION['token'] = $token;
?>
<form action="./result.php" method="post">
  <input type="text" name="field1">
  <input type="hidden" name="token" value="<?php echo $token;?>">
  <input type="submit">
</form>

uniqid()

マイクロ秒単位の現在時刻にもとづいた、接頭辞つきの一意な ID を取得します。

公式ドキュメント:PHP: uniqid – Manual

送信先画面

<?php
session_start();
$token = isset($_POST['token']) ? $_POST['token'] : "";
$session_token = isset($_SESSION['token']) ? $_SESSION['token'] : "";
unset($_SESSION['token']);

if($token != "" && $token == $session_token) {
  // 送信時の処理をここに書く
  var_dump($_POST['field1']);
}else{
  // 再送信だった場合は入力画面に戻す
  header('Location: ./input.php');
  exit();
}

入力画面の <input name="token"> にセットされたトークン($token)と、セッションとして保存したトークン($session_token)を比較して、一致していたら処理を進めます。

送信先画面をリロードすると、ブラウザから「再送信しますか?」というポップアップが出ると思いますが、5行目でセッションのトークンを破棄しているため上の条件が不一致になります。
上記のコードでは、不一致の場合は入力画面に遷移させています。