Предотвращение повторной подачи формы - PullRequest
103 голосов
/ 13 октября 2010

Первая страница содержит форму HTML. Вторая страница - код, который обрабатывает представленные данные.

Форма на первой странице отправляется. Браузер перенаправляется на вторую страницу. Вторая страница обрабатывает представленные данные.

В этот момент, если обновляется вторая страница, появляется предупреждение «Подтвердить повторную отправку формы».

Можно ли это предотвратить?

Ответы [ 11 ]

143 голосов
/ 19 октября 2010

Есть два подхода, которые люди использовали здесь:

Метод 1: Использование AJAX + Redirect

Таким образом, вы отправляете свою форму в фоновом режиме, используя JQuery или что-то похожее на Page2, в то время как пользователь по-прежнему видит страницу 1 отображаемой. После успешной публикации вы перенаправляете браузер на страницу Page2.

Способ 2: Пост + перенаправление на себя

Это распространенная техника на форумах. Форма на Page1 отправляет данные на Page2, страница2 обрабатывает данные и делает то, что нужно сделать, а затем выполняет перенаправление HTTP на себя. Таким образом, последнее «действие», которое запоминает браузер, - это простое GET на странице 2, поэтому форма не будет повторно отправлена ​​после F5.

22 голосов
/ 30 сентября 2015

Вам нужно использовать PRG - Post / Redirect / Get pattern , и вы только что реализовали P из PRG.Вам нужно Redirect . (В наши дни перенаправление вообще не нужно. См. this )

PRG - шаблон проектирования веб-разработки, который предотвращает некоторыедублирующая отправка формы, что означает, Отправить форму (Отправить запрос 1) -> Перенаправление -> Получить (Запрос 2)

Under the hood

Код состояния перенаправления - HTTP 1.0 с HTTP 302 или HTTP 1.1с HTTP 303

Ответ HTTP с кодом состояния перенаправления дополнительно предоставит URL в поле заголовка местоположения.Пользовательский агент (например, веб-браузер) приглашается в ответ с этим кодом, чтобы сделать второй, в остальном идентичный, запрос на новый URL-адрес, указанный в поле местоположения.

Код состояния перенаправления должен гарантировать, что в этой ситуации браузер веб-пользователя сможет безопасно обновить ответ сервера, не вызывая повторную отправку исходного запроса HTTP POST.

Double Submit Problem

Double Submit Problem

Post/Redirect/Get Solution

Post/Redirect/Get Solution

Источник

10 голосов
/ 13 октября 2010

Непосредственно, вы не можете, и это хорошо.У браузера есть причина по причине.Эта ветка должна ответить на ваш вопрос:

Запретить кнопке «Назад» отображать оповещение о подтверждении POST

Были предложены два ключевых обходных пути: шаблон PRG и отправка AJAX с последующим сценарием.Перемещение.

Обратите внимание, что если ваш метод допускает GET, а не метод отправки POST, то это решило бы проблему и лучше соответствовало бы соглашению.Эти решения предоставляются при условии, что вы хотите / должны POST-данные.

7 голосов
/ 21 октября 2010

Единственный способ быть на 100% уверенным в том, что одна и та же форма никогда не будет отправлена ​​дважды, - это вставить уникальный идентификатор в каждый выпускаемый вами файл и отследить, какие из них были отправлены на сервер. Подводный камень в том, что если пользователь выполняет резервное копирование на страницу, где находилась форма, и вводит новые данные, эта же форма не будет работать.

6 голосов
/ 21 октября 2010

Ответ состоит из двух частей:

  1. Убедитесь, что повторяющиеся записи не связываются с вашими данными на стороне сервера.Для этого вставьте уникальный идентификатор в сообщение, чтобы вы могли отклонить последующие запросы на стороне сервера.Этот шаблон называется Идемпотентный приемник в терминах обмена сообщениями.

  2. Убедитесь, что пользователь не обеспокоен возможностью повторных отправок обоими

    • перенаправление на GET после POST (шаблон POST redirect GET)
    • отключение кнопки с помощью javascript

Ничто из того, что вы сделаете в 2., полностью не помешаетдубликаты представляются.Люди могут кликать очень быстро, а хакеры могут оставлять сообщения в любом случае.Вам всегда нужно 1. если вы хотите быть абсолютно уверены, что нет дубликатов.

2 голосов
/ 02 мая 2017

Ну, я обнаружил, что никто не упомянул этот трюк.

Без перенаправления вы все равно можете запретить подтверждение формы при обновлении.

По умолчанию код формы такой:

<form method="post" action="test.php">

сейчас, измените его на <form method="post" action="test.php?nonsense=1">

Вы увидите магию.

Я думаю, это потому, что браузеры не будутвызвать всплывающее окно с уведомлением о подтверждении, если оно получает метод GET (строку запроса) в URL.

2 голосов
/ 15 октября 2010

Если вы обновите страницу данными POST, браузер подтвердит вашу повторную отправку. Если вы используете данные GET, сообщение не будет отображаться. Вы также можете получить вторую страницу, после сохранения отправки, перенаправить на третью страницу без данных.

0 голосов
/ 26 июня 2019

используйте js для предотвращения добавления данных:

if ( window.history.replaceState ) {
    window.history.replaceState( null, null, window.location.href );
}
0 голосов
/ 19 октября 2017

Попробуйте трис:

function prevent_multi_submit($excl = "validator") {
    $string = "";
    foreach ($_POST as $key => $val) {
    // this test is to exclude a single variable, f.e. a captcha value
    if ($key != $excl) {
        $string .= $key . $val;
    }
    }
    if (isset($_SESSION['last'])) {
    if ($_SESSION['last'] === md5($string)) {
        return false;
    } else {
        $_SESSION['last'] = md5($string);
        return true;
    }
    } else {
    $_SESSION['last'] = md5($string);
    return true;
    }
}

Как использовать / пример:

if (isset($_POST)) {
    if ($_POST['field'] != "") { // place here the form validation and other controls
    if (prevent_multi_submit()) { // use the function before you call the database or etc
        mysql_query("INSERT INTO table..."); // or send a mail like...
        mail($mailto, $sub, $body); // etc
    } else {
        echo "The form is already processed";
    }
    } else {
    // your error about invalid fields
    }
}

Шрифт: https://www.tutdepot.com/prevent-multiple-form-submission/

0 голосов
/ 24 мая 2017

Мне очень нравится ответ @ Angelin.Но если вы имеете дело с каким-то устаревшим кодом, где это непрактично, этот метод может работать для вас.

В верхней части файла

// Protect against resubmits
if (empty($_POST))  {
   $_POST['last_pos_sub'] = time();
} else {
     if (isset($_POST['last_pos_sub'])){
        if ($_POST['last_pos_sub'] == $_SESSION['curr_pos_sub']) {
           redirect back to the file so POST data is not preserved
        }
        $_SESSION['curr_pos_sub'] = $_POST['last_pos_sub'];
     }
}

Затем в концеФорма, введите last_pos_sub следующим образом:

<input type="hidden" name="last_pos_sub" value=<?php echo $_POST['last_pos_sub']; ?>>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...