お問い合わせフォームへの連投を防ぐ方法+α

お問い合わせフォームへの連投を防ぐ方法+α

お問い合わせフォームに何の対策もしていないと、完了画面でブラウザの更新(F5)を押した時にメールが2通飛んでしまう、といったことが起こります。
それを防ぐ為のプログラミングの仕方に関して、メモ的にエントリーします。


何も対策をしていないと、いたずらにあった場合に大変なことに

特に意識せずにプログラミングしている場合、こんな感じになると思います。
<?php
/*----- 入力フォーム -----*/
// 何もなし
?>
<form action="ex1_end.php" method="POST">
<textarea name="note">お問い合わせっぽいもの</textarea>
<textarea name="note">実際は送信しないよ</textarea>

<input type="submit" name="submitBtn" value="送信!" /></form>
<?php
/*----- 完了画面 -----*/
// 送信処理を記述
?>

送信されました!

サンプルを準備しましたので、確認してみてください。
サンプル1

【送信!】ボタンを押すと、完了画面に移動します。
実際にメールは私の方に飛んできませんので、安心して押しまくってください。
その後、完了画面でブラウザの更新(F5)を押すと、次の画面が出てきます。
(画面はFirefox)
アラート

ここで【再送信】を押すと、何も対策をしていなければ再度メールが飛びます。
ブラウザの更新(F5)を押せば押すほど、何回でも出来てしまいますので、メール送信の機能をつけていたら私のメールボックスが大変なことになってしまいます。


連投されないための対策

そこで、対策をしたものが次のサンプルです。
サンプル2

一見同じに見えますが、完了画面にてブラウザの更新(F5)を押し、【再送信】してみてください。
画面に表示されるメッセージが「失敗しました」に変わると思います。

プログラムとしては、次のように記述しています。
<?php
/*----- 入力フォーム -----*/
// セッション開始
	session_start();

// タイムスタンプと推測できない文字列にてキーを発行
	$key = md5(time()."推測できない文字列");

// 発行したキーをセッションに保存
	$_SESSION['key'] = $key;
?>

<form action="ex2_end.php" method="POST">
<textarea name="note">
お問い合わせっぽいもの
実際は送信しないよ
</textarea>
<br />
<input type="submit" name="submitBtn" value="送信!" />
<input type="hidden" name="key" value="<? print $key ?>" />
</form>
<?php
/*----- 完了画面 -----*/
// セッション開始
	session_start();
	
// 変数宣言
	$msg = "";
	
// セッションに保持されているキーと、POSTで飛んできたキーが同じかどうか判別
	if (	isset($_SESSION['key']) && 
			isset($_POST['key']) && 
			$_SESSION['key'] == $_POST['key']) {

// 合致しているので、送信処理を記述
		$msg = "送信しました";
	}
	else {
// 合致していないので、送信しない
		$msg = "失敗しました";
	}
	
// セッションに保持されているキーを破棄する ※重要※
	unset($_SESSION['key']);
?>

<? print $msg ?>
ポイントとしては、
  • 入力画面にてチェック用のキーを発行し、セッションに保存。
  • お問い合わせの内容と一緒に、チェック用のキーをPOSTにて送信。
  • 完了画面にて、送信処理の前にセッションに保持されているチェック用のキーと、POSTで飛んできた値が合致しているかチェック。
  • 処理後、セッションに保持されているキーを破棄 ※重要※
になります。
こうすることで、一度送信した後は送信されなくなります。
簡単ですね!

注意としては、最後にキーを破棄しておかないとまったく意味が無いので、最後は必ず不要になったキーを破棄してください。

おまけ

実は、このプログラム手法によって、クロスサイトリクエストフォージェリ(CSRF)の対策にもなっています。
攻撃ページから「end.php」に対してPOSTでデータを送信しても、セッション内に保持しているキーの値と、POSTで飛んでくるキーの値が合致しないので、攻撃が成立しません。
(※100%攻撃を防ぐ保障をするものではありません。複合的な要因により、攻撃出来る可能性は0ではないと思います。)


記事のタイトルには「お問い合わせフォーム」と書きましたが、様々なフォームで利用できるものですので、必要に応じて内容を変えつつ利用してください。
ちょっぴり幸せになれるかもしれませんよ。
Tag ,

コメントを残す