web-dev-qa-db-ja.com

「フォームの再送信の確認」ダイアログを防ぐ方法

送信後にフォームの情報を消去して、ページの更新後にこのエラーが表示されないようにするにはどうすればよいですか?

画像を見る(クロームから):

ダイアログには次のテキストがあります。

探しているページは使用しました
入力した情報。それに戻る
ページは、あなたがとった行動を引き起こす可能性があります
繰り返しました。続けますか?

このダイアログが表示されないようにします。

21
Martin Rose

Edit:この回答を最初に投稿してから数年が経ち、いくつかの賛成票を受け取ったにもかかわらず、以前の回答にあまり満足していないので、完全にやり直しました。これがお役に立てば幸いです。


GETおよびPOSTを使用する場合:

このエラーメッセージを取り除く1つの方法は、フォームでGETではなくPOSTを使用することです。これは常に適切な解決策ではない(以下を参照)であることを覚えておいてください。

POSTを常に使用します。繰り返したくないアクションを実行している場合、機密情報が転送されている場合、またはフォームにファイルのアップロードまたは送信されたすべてのデータの長さが含まれる場合 〜2000文字 より長い。

POSTを使用する場合の例は次のとおりです。

  • ログインフォーム
  • お問い合わせフォーム
  • 支払いフォームの送信
  • データベースのエントリを追加、編集、または削除するもの
  • 画像アップローダー(注:GET<input type="file">フィールドと共に使用すると、ファイル名のみがサーバーに送信されます。99.73%の時間はあなたの望むものではありません。)
  • 多くのフィールドを持つフォーム(GETを使用すると長いURLが作成されます)

これらのいずれの場合も、ページを更新してデータを再送信することは望ましくありません。機密情報を送信している場合、GETの使用は不適切であるだけでなく、機密事項(ユーザーのパスワードなど)があるため、セキュリティ問題(フォームがAJAXによって送信された場合でも)になります。 URLで送信されるため、サーバーアクセスログに表示されます。

基本的にその他の場合はGETを使用します。これは、繰り返されるかどうか気にしない場合、直接リンクを提供できるもの、機密情報が転送されない場合、URLの長さが制御不能にならないことを確信している場合、フォームにファイルのアップロードがない場合。

例は次のとおりです。

  • 検索エンジンで検索を実行する
  • Webサイト内を移動するためのナビゲーションフォーム
  • ナンスまたは使い捨てパスワード(電子メールの「登録解除」リンクなど)を使用して1回限りのアクションを実行する。

これらの場合、POSTは完全に不適切です。検索エンジンが検索にPOSTを使用した場合を想像してください。ページを更新するたびにこのメッセージが表示され、結果のURLをコピーして他の人に貼り付けることができず、フォーム自体を手動で入力する必要があります。

POSTを使用する場合:

私にとって、ほとんどの場合、「フォームの再送信を確認」ダイアログがポップアップ表示されていても、設計上の問題があることがわかります。破壊的なアクションを実行するために使用されるPOSTの性質により、Webデザイナーは、ユーザーが誤って(または意図的に)ページを更新することにより、ユーザーがこれらのアクションを複数回実行しないようにする必要があります。多くのユーザーは、このダイアログの意味すら知らないため、[続行]をクリックするだけです。それが「支払いの送信」リクエストの後だったらどうなりますか?支払いは再度送られますか?

それで、あなたは何をしますか?幸いなことに Post/Redirect/Get デザインパターンがあります。ユーザーがPOST要求をサーバーに送信すると、サーバーはユーザーのブラウザーを別のページにリダイレクトし、GETを使用してそのページを取得します。

PHPを使用した簡単な例を次に示します。

if(!empty($_POST['username'] && !empty($_POST['password'])) {
    $user = new User;
    $user->login($_POST['username'], $_POST['password']);

    if ($user->isLoggedIn()) {
        header("Location: /admin/welcome.php");
        exit;
    }
    else {
        header("Location: /login.php?invalid_login");
    }
}

この例では、パスワードがincorrectであっても、ログインフォームにリダイレクトしていることに注意してください。無効なログインメッセージをユーザーに表示するには、次のようにします。

if (isset($_GET['invalid_login'])) {
    echo "Your username and password combination is invalid";
}
19
Mike

フォームやその中の値とは関係ありません。ブラウザによって起動され、ユーザーがキャッシュされたデータで同じリクエストを繰り返すことを防ぎます。結果ページの更新を本当に有効にする必要がある場合は、PHP(header('Location:result.php');)または使用している他のサーバー側言語を介してユーザーをリダイレクトする必要があります。メタタグソリューションは、更新時に再送信を無効にするためにも機能するはずです。

8
zatatatata

POSTページを処理した後、ユーザーを同じページにリダイレクトします。

オン http://test.com/test.php

header('Location: http://test.com/test.php');

ページを更新してもデータは再送信されないため、これによりボックスは削除されます。

5

JQueryでAJAX呼び出しを使用してみてください。YouTubeが更新せずにコメントを追加する方法のように。

Ajaxコールで必要な情報を送信する必要があります。
例としてyoutubeコメントを使用します。

$.ajax({
    type: 'POST',
    url: 'ajax/comment-on-video.php',
    data: {
        comment: $('#idOfInputField').val();
     },
    success: function(obj) {
        if(obj === 'true') {
            //Some code that recreates the inserted comment on the page.
        }
    }
});

これでファイルを作成できますcomment-on-video.phpそして次のようなものを作成します。

<?php
    session_start();

    if(isset($_POST['comment'])) {
        $comment = mysqli_real_escape_string($db, $_POST['comment']);
        //Given you are logged in and store the user id in the session.
        $user = $_SESSION['user_id'];

        $query = "INSERT INTO `comments` (`comment_text`, `user_id`) VALUES ($comment, $user);";
        $result = mysqli_query($db, $query);

        if($result) {
            echo true;
            exit();
        }
    }
    echo false;
    exit();
?>
2

上記の回答のいずれも使用できない状況がありました。私のケースは、検索結果に移動した後に「戻る」をクリックすると、ユーザーが「フォームの再送信を確認」する検索ページでの作業に関係していました。この問題を回避する次のjavascriptを書きました。それは少し派手なので、大きな修正ではありません。IE8以前では動作しません。それでも、これはこの問題を扱う人にとって有用または興味深いかもしれませんが。

jQuery(document).ready(function () {

//feature test
if (!history)
    return;

var searchBox = jQuery("#searchfield");

    //This occurs when the user get here using the back button
if (history.state && history.state.searchTerm != null && history.state.searchTerm != "" && history.state.loaded != null && history.state.loaded == 0) {

    searchBox.val(history.state.searchTerm);

    //don't chain reloads
    history.replaceState({ searchTerm: history.state.searchTerm, page: history.state.page, loaded: 1 }, "", document.URL);

    //perform POST
    document.getElementById("myForm").submit();

    return;
}

    //This occurs the first time the user hits this page.
history.replaceState({ searchTerm: searchBox.val(), page: pageNumber, loaded: 0 }, "", document.URL);

});
1
Felix Steiny

あなたが探しているようです Post/Redirect/Get パターン。

別の解決策として、リダイレクトをまったく使用しないようにすることもできます。

POST確認アラートなしで、処理結果を一度に処理およびレンダリングできます。ブラウザの履歴オブジェクトを操作するだけです:

history.replaceState("", "", "/the/result/page")

full または short の回答を参照してください

0
Eugen Konkov

同じ問題がありました

これは私のために働いた、

echo("<script>location.href = 'http://localhost/pagename.html';</script>");
0
Sachi.Dila