PHP初心者です。簡単に書くと、このようなswitch文を書いています。


switch ($hoge) {
case "a":
update(); // DB更新
hyoji(); // 回答一覧表示
break;
default:
question(); // 質問表示
}

question()のチェックボックスフォームにhiddenでhogeを置き、aをPOST送信してupdate()、hyoji()を実行するというプログラムなのですが、ひとつ欠陥があります。hyoji()画面で画面更新を行うと、再度update()にPOST=aが渡されDBに再び値が渡ってしまいます。

これを解消する方法についてご教授いただけませんでしょうか?なお、利用は携帯およびPCを考えています。

URLは事前にGETでhttp://hoge.com/abc.php?aaa=1というようになっており、各URLで回答者は1度きりしか回答できないようになると一番いいです(しかしそこまでする必要もないとも思っていて、連続更新を防げばよいと考えています)。

以上、どうぞよろしくお願いします。

回答の条件
  • URL必須
  • 1人2回まで
  • 登録:2009/06/20 00:07:45
  • 終了:2009/06/20 09:38:33

ベストアンサー

id:b-wind No.1

b-wind回答回数3344ベストアンサー獲得回数4402009/06/20 00:21:45

ポイント50pt

色々やり方はあるけど、シンプルな例としてはトークンを使う方法。

[PHP-users 19497]Re: 重複投稿/submitを防ぐトランザクショントークンという考え方

id:satoshi07

mt_srand((double)microtime()*1000000);

$token = md5((string)mt_rand()); //必要ならユーザー名とか

//メールアドレス等も入れて

//md5化するとGOOD(?)

session_start();

$_SESSION["token"] = $token;

?>

<body>

switch ($act) {

case "a": // 回答一覧表示

sleep(1);//重複submitを起こしやすくする。実際にはいらない

session_start();

if ( empty($_POST["token"]) || $_POST["token"] != $_SESSION["token"] ) {

echo "エラーだよん";

} else {

unset($_SESSION["token"]);

//ここから先に正常時の処理を続けて書く

update_an();

}

gamen_iti();

break;

default: // 質問表示

gamen_q();

}

?>

</body>

※簡略化してます。

としたのですが、「エラーだよん」が出力されます。1度目のquestion()からのPOST送信でもです。$_POST["token"]、$_SESSION["token"]の中身を見たところ、異なる値になっています。

2009/06/20 02:13:33

その他の回答(2件)

id:b-wind No.1

b-wind回答回数3344ベストアンサー獲得回数4402009/06/20 00:21:45ここでベストアンサー

ポイント50pt

色々やり方はあるけど、シンプルな例としてはトークンを使う方法。

[PHP-users 19497]Re: 重複投稿/submitを防ぐトランザクショントークンという考え方

id:satoshi07

mt_srand((double)microtime()*1000000);

$token = md5((string)mt_rand()); //必要ならユーザー名とか

//メールアドレス等も入れて

//md5化するとGOOD(?)

session_start();

$_SESSION["token"] = $token;

?>

<body>

switch ($act) {

case "a": // 回答一覧表示

sleep(1);//重複submitを起こしやすくする。実際にはいらない

session_start();

if ( empty($_POST["token"]) || $_POST["token"] != $_SESSION["token"] ) {

echo "エラーだよん";

} else {

unset($_SESSION["token"]);

//ここから先に正常時の処理を続けて書く

update_an();

}

gamen_iti();

break;

default: // 質問表示

gamen_q();

}

?>

</body>

※簡略化してます。

としたのですが、「エラーだよん」が出力されます。1度目のquestion()からのPOST送信でもです。$_POST["token"]、$_SESSION["token"]の中身を見たところ、異なる値になっています。

2009/06/20 02:13:33
id:y-kawaz No.2

y-kawaz回答回数1421ベストアンサー獲得回数2262009/06/20 00:33:46

ポイント20pt

リロードによる再POST防止はPOST時に一度Locationでリダイレクトすることで実現できます。

質問者のプログラム例では例えば以下のように修正すれば大筋は良いと思います。

<?php
switch ($hoge) {
  case "a": 
    update(); // DB更新
    header("Location: ".$_SERVER['SCRIPT_URI'].'?hoge=b');
    exit;
  case "b":
    hyoji(); // 回答一覧表示
    break;
  default: 
    question(); // 質問表示
}
?>

http://q.hatena.ne.jp/answer

id:satoshi07

echo $_SERVER['SCRIPT_URI'] で値が出ません。それゆエラーが出ます。

Warning: Cannot modify header information - headers already sent by...

$_SERVER["PHP_SELF"]や$_SERVER["QUERY_STRING"]は出ます。

またPOSTで動いており、'?hoge=b'は適切ではないような気がします。$hogeにbが渡らないですよね?初心者なので、認識違いでしたら申し訳ございません。

2009/06/20 02:02:19

質問者が未読の回答一覧

 回答者回答受取ベストアンサー回答時間
1 にんにん 16 14 1 2009-06-20 03:37:16
  • id:b-wind
    >「エラーだよん」が出力されます。
    それ1ファイル内のソース?なんで session_start() が2回あるの?
    で、POST された後に token 再生成してるよね?一致する分けないと思うんだけど。
  • id:satoshi07
    すみません、思いきり寝ぼけていました。
    トークンを使うということで調べてみたところ、できそうです。
    ありがとうございました!

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません