Предотвращение повторной подачи формы

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

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

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

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

100 голосов | спросил Emanuil Rusev 13 +04002010-10-13T17:02:31+04:00312010bEurope/MoscowWed, 13 Oct 2010 17:02:31 +0400 2010, 17:02:31

10 ответов


0

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

Метод 1: используйте AJAX + Redirect

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

Метод 2: публикация + перенаправление на себя

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

ответил CodeTwice 19 +04002010-10-19T15:56:30+04:00312010bEurope/MoscowTue, 19 Oct 2010 15:56:30 +0400 2010, 15:56:30
0

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

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

Under the hood

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

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

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

Double Submit Problem

 Задача двойной отправки

Post/Redirect/Get Solution

 Опубликовать /Перенаправить /Получить Решение

Источник

ответил Angelin Nadar 30 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowWed, 30 Sep 2015 15:43:41 +0300 2015, 15:43:41
0

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

Кнопка «Назад» не отображает предупреждение о подтверждении POST

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

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

ответил davin 13 +04002010-10-13T17:23:16+04:00312010bEurope/MoscowWed, 13 Oct 2010 17:23:16 +0400 2010, 17:23:16
0

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

ответил Blrfl 21 +04002010-10-21T06:28:27+04:00312010bEurope/MoscowThu, 21 Oct 2010 06:28:27 +0400 2010, 06:28:27
0

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

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

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

    • перенаправление на GET после процедуры POST (шаблон GET для перенаправления GET)
    • отключение кнопки с помощью JavaScript

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

ответил iwein 21 +04002010-10-21T20:25:43+04:00312010bEurope/MoscowThu, 21 Oct 2010 20:25:43 +0400 2010, 20:25:43
0

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

ответил Joel 15 +04002010-10-15T20:40:40+04:00312010bEurope/MoscowFri, 15 Oct 2010 20:40:40 +0400 2010, 20:40:40
0

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

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

По умолчанию код формы выглядит следующим образом:

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

Теперь измените его на <form method="post" action="test.php?nonsense=1">

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

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

ответил Highlight 2 Mayam17 2017, 00:13:28
0

Шаблон PRG может предотвратить повторную отправку, вызванную обновлением страницы. Это не 100% безопасная мера.

Обычно я буду предпринимать действия, указанные ниже, чтобы предотвратить повторную отправку:

  1. Клиентская сторона - используйте javascript для предотвращения повторных нажатий на кнопку, которая приведет к отправке формы. Вы можете просто отключить кнопку после первого щелчка.

  2. Серверная сторона - я вычислю хэш на переданных параметрах и сохраню этот хэш в сеансе или базе данных, поэтому, когда была получена дублированная отправка, мы можем обнаружить дублирование, а затем правильно ответить клиенту. Однако вы можете создать хеш на стороне клиента.

В большинстве случаев эти меры могут помочь предотвратить повторное представление.

ответил ehe888 18 J000000Monday16 2016, 06:40:02
0

Мне очень нравится ответ @ 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']; ?>>
ответил Scott C Wilson 24 Maypm17 2017, 23:05:05
0

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

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
    }
}
шрифт форм-представление /
ответил Rômulo Z. C. Cunha 19 +03002017-10-19T19:12:58+03:00312017bEurope/MoscowThu, 19 Oct 2017 19:12:58 +0300 2017, 19:12:58

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132