как я могу избавиться от повторной заявки на подтверждение формы в HTML / PHP? [Дубликат]

Это одно из самых запутанных сообщений об ошибках, которые каждый программист VC ++ видел снова и снова. Давайте сначала сделаем чёткость.

A. Что такое символ? Короче говоря, символ - это имя. Это может быть имя переменной, имя функции, имя класса, имя typedef или что-либо кроме тех имен и знаков, которые принадлежат языку C ++. Он определяется пользователем или вводится библиотекой зависимостей (другой пользовательский).

B. Что является внешним? В VC ++ каждый исходный файл (.cpp, .c и т. Д.) Рассматривается как единица перевода, компилятор компилирует по одному модулю за раз и генерирует один объектный файл (.obj) для текущей единицы перевода. (Обратите внимание, что каждый заголовочный файл, включенный в этот исходный файл, будет предварительно обработан и будет рассматриваться как часть этой единицы перевода). Все внутри единицы перевода считается внутренним, все остальное считается внешним. В C ++ вы можете ссылаться на внешний символ, используя ключевые слова, такие как extern, __declspec (dllimport) и т. Д.

C. Что такое «решимость»? Resolve - термин времени связывания. Во время компоновки линкер пытается найти внешнее определение для каждого символа в объектных файлах, которые не могут найти свое определение внутри. Объем этого процесса поиска, включая:

  • Все объектные файлы, сгенерированные во время компиляции
  • Все библиотеки (.lib), которые явно или неявно указаны как дополнительные зависимости это строительное приложение.

Этот процесс поиска называется разрешением.

D. Наконец, почему Unresolved External Symbol? Если компоновщик не может найти внешнее определение для символа, который не имеет определения внутри, он сообщает об ошибке неразрешенного внешнего символа.

E. Возможные причины LNK2019: ошибка неразрешенного внешнего символа. Мы уже знаем, что эта ошибка связана с тем, что компоновщик не смог найти определение внешних символов, возможные причины могут быть отсортированы как:

  1. Определение существует

Например, если у нас есть функция foo, определенная в a.cpp:

int foo()
{
    return 0;
}

В b.cpp мы хотим вызвать функцию foo, поэтому добавим

void foo();

, чтобы объявить функцию foo () и вызвать ее в другом теле функции, скажем bar():

void bar()
{
    foo();
}

Теперь, когда вы создаете этот код, вы получите ошибку LNK2019, жалуясь, что foo является неразрешенным символом , В этом случае мы знаем, что foo () имеет свое определение в a.cpp, но отличается от того, которое мы вызываем (другое возвращаемое значение). Это означает, что определение существует.

  1. Определение не существует

Если мы хотим вызвать некоторые функции в библиотеке, но библиотека импорта не добавлен в дополнительный список зависимостей (установленный из: Project | Properties | Configuration Properties | Linker | Input | Additional Dependency) вашего проекта. Теперь компоновщик сообщит LNK2019, поскольку определение не существует в текущей области поиска.

98
задан iwein 3 September 2013 в 07:28
поделиться

10 ответов

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

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

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

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

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

133
ответ дан CodeTwice 25 August 2018 в 16:27
поделиться

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

6
ответ дан Blrfl 25 August 2018 в 16:27
поделиться

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

Кнопка «Предотвратить обратную связь» для подтверждения оповещения о подтверждении POST

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

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

9
ответ дан Community 25 August 2018 в 16:27
поделиться

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

Как правило, я буду принимать действия ниже для предотвращения повторной отправки:

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

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

0
ответ дан ehe888 25 August 2018 в 16:27
поделиться
20
ответ дан Eugen Konkov 25 August 2018 в 16:27
поделиться

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

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

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

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

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

Вы увидите волшебство.

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

2
ответ дан Highlight 25 August 2018 в 16:27
поделиться

Ответ на две части:

  1. Убедитесь, что дублирующиеся сообщения не конфликтуют с вашими данными на стороне сервера. Для этого вставьте уникальный уникальный идентификатор в сообщение, чтобы вы могли отказаться от последующих запросов на стороне сервера. Этот шаблон называется Idempotent Receiver в терминах обмена сообщениями.
  2. Убедитесь, что пользователь не обеспокоен возможностью дублирования отправки как путем перенаправления на GET после POST (POST redirect GET шаблон) отключение кнопки с помощью javascript

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

6
ответ дан iwein 25 August 2018 в 16:27
поделиться

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

2
ответ дан Joel 25 August 2018 в 16:27
поделиться

Попробуйте tris:

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 -форма-представление /

0
ответ дан Rômulo Z. C. Cunha 25 August 2018 в 16:27
поделиться

Мне очень нравится ответ @ 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']; ?>>
0
ответ дан Scott C Wilson 25 August 2018 в 16:27
поделиться