web-dev-qa-db-ja.com

戻るボタンを押したときにフォームの再送信を防ぐ

ここや他の場所で多くの投稿を検索しましたが、私の問題の解決策が見つからないようです。データベースエントリを表示するページがあります:database.php。これらのエントリは、フォームを使用してフィルタリングできます。それらをフィルターし、興味のあるものだけを表示する場合、エントリーをクリックして(リンクとして)、そのエントリーページに移動できます(php GET経由)。そのエントリページ(つまり、 "view.php?id = 1")で[戻る]ボタン(database.phpに戻る)を押すと、フィルターフォームはフォームの再送信を確認する必要があります。これを防ぐ方法はありますか?

以下に、いくつかの(簡略化された)コード例を示します。

Database.php:

<form>
    <select>
        <option>1</option>
        <option>2
        <option>
    </select>
    <input type="submit" name="apply_filter" />
</form>
<?php
if ( isset( $_POST[ "apply_filter" ] ) ) { // display filtered entries
    $filter = $_POST[ "filter" ];
    $q = "Select * from table where col = '" . $filter . "'";
    $r = mysql_query( $q );
} else { // display all entries
    $q = "Select * from table";
    $r = mysql_query( $q );
}
while ( $rec = mysql_fetch_assoc( $r ) ) {
    echo "<a href='view.php?id=" . $rec[ "id" ] . "'>" . $rec[ "name" ] . "</a><br />"; // this is where the link to the view.php page is...
}
?>

今述べたように、リンクをクリックすると、「view.php?id = whatever」に移動します。そのページで、URLからIDを取得して、その単一のエントリを表示します。

view.php:

<?php
$id = $_GET[ "id" ];
$q = "Select * from table where id = '" . $id . "'";
$r = mysql_query( $q );
while (  ) {
    // display entry
}

?>

ここで戻るボタンを押すと、database.phpのフォーム(DBの結果のフィルタリングに使用されるフォーム)で再送信の確認が必要になります。これは非常に迷惑なだけでなく、私にとっても役に立たない。

どうすれば修正できますか?コード例と問題の説明で十分であることを願っています。私に知らせていない場合は、指定しようとします。

20
user1889382

私はこの質問が古いことを知っていますが、この問題を自分で抱えていると、私が発見した2つの行は次のとおりです:

header("Cache-Control: no cache");
session_cache_limiter("private_no_expire");
23

これを行うには、2つの方法があります。簡単な方法と難しい方法。

方法に関係なく、状態ベースのページ($_SESSIONを使用)を扱っている場合、ページを「ライブ」に保ち、制御下に置くために、このようなすべてのページのキャッシュを防止します。 :

<?php
//Set no caching
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); 
header("Cache-Control: no-store, no-cache, must-revalidate"); 
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
?>

難しい方法は、idを生成し、非表示の入力または&_SESSION cookieとしてページのどこかに保存することです。次に、サーバーに同じIDを$_SESSIONとして保存します。それらが一致しない場合、事前にプログラムされた一連のifelse typeステートメントにより、ページが再送信されると何も起こりません(これは、クリックして戻るときに実行しようとします)。

簡単な方法は、次のように、フォームが正常に送信された場合、ユーザーをフォーム送信ページにリダイレクトすることです。

header('Location: http://www.mydomain.com/redirect.php');

これがお役に立てば幸いです!

8
Phillip Berger

役立つのは、フィルターフォームにGETの代わりにPOSTメソッドを使用させることです。

ブラウザーは通常、POST入力が自動的に再送信されるのを防ぎます。これは、GET入力が使用されている場合は実行されません。また、これにより、ユーザーはフィルターを使用してページにリンクできます。

3
tanios

ページがリロードされた場合、またはリロードされたときに機能する代替ソリューションには、$ _ SESSIONを使用して投稿のオリジナリティをチェックすることが含まれます。一言で言えば、一意またはランダムな文字列を確認してください。

フォームで、Rand()またはmicrotime()を使用して値が設定された入力要素を追加します。

<input type="hidden" name="formToken" value="<?php echo microtime();?>"/>

そして、PHP関数をラップして、ifブロックのフォームデータを検証および解析します。

if(!isset($_SESSION['formToken']) || $_POST['formToken'] !== $_SESSION['formToken'])){
       $_SESSION['formToken'] = $_POST['formToken'];
      /*continue form processing */
}
0
SilentStone

ユーザーが戻るボタンを使用してページにアクセスしたかどうかを検出するにはどうすればよいですか? この場合、JavaScriptを使用してページをリロードしました。ページがリロードされると、コードがすでに対応する検証を処理して、フォームが2回送信されないようにします。私の場合の重要な部分は、ブラウザーの「戻る」ボタンをクリックした後にフォームが再表示されたときに、ページの再ロードを強制することでした。これは、この検証を適用したいURLのコードです。

<script type="text/javascript">
    if (window.performance && window.performance.navigation.type == window.performance.navigation.TYPE_BACK_FORWARD) {
        location.reload();
    }
</script>
0
Jaime Montoya

header( "Cache-Control:no cache");

session_cache_limiter( "private_no_expire");

注:その後、フォームから送信した投稿データを使用した後、これらの2行をfunction.soの最後で使用する必要があります。リダイレクトされたページに戻ったときに、ページの再送信を求められません。これは動作します。

0