Как предотвратить множественные вставки при отправке формы в PHP?

Иногда пользователь может дважды нажать Enter , и сообщение будет вставлено дважды.

Есть ли решение предотвратить это, кроме как проверить, есть ли сообщение с тем же title и content ?

Существует несколько решений этой проблемы:

  1. Используйте Javascript, чтобы отключить кнопку отправки формы при ее отправке. Недостатком этого является то, что это АБСОЛЮТНО не является надежным способом. Очень легко отправить формы без нажатия кнопки, и это также не сработает для пользователей с отключенным JavaScript. Я бы определенно не рекомендовал этот метод.

    Пример:

     <script language="javascript"> <!-- function disableSubmitButton() { // you may fill in the blanks :) } --> </script> <form action="foo.php" method="post"> <input type="text" name="bar" /> <input type="submit" value="Save" onclick="disableSubmitButton();"> </form> 
  2. Используйте сеансы PHP для установки переменной сеанса (например, $ _SESSION ['posttimer']) в текущую временную метку для сообщения. Прежде чем обрабатывать форму в PHP, проверьте, существует ли переменная $ _SESSION ['posttimer'] и проверяет определенную временную разницу (IE: 2 секунды). Таким образом, вы можете легко отфильтровать двойные представления.

    Пример:

     // form.html <form action="foo.php" method="post"> <input type="text" name="bar" /> <input type="submit" value="Save"> </form> // foo.php if (isset($_POST) && !empty($_POST)) { if (isset($_SESSION['posttimer'])) { if ( (time() - $_SESSION['posttimer']) <= 2) { // less then 2 seconds since last post } else { // more than 2 seconds since last post } } $_SESSION['posttimer'] = time(); } 
  3. Включите уникальный токен в каждом POST. В этом случае вы также должны установить переменную сеанса в токен, который хотите включить, а затем отобразить токен в форме. После отправки формы вы повторно создаете токен. Когда поданный токен не совпадает с токеном в вашей сессии, форма была повторно отправлена ​​и должна быть объявлена ​​недействительной.

    Пример:

     // form.php <?php // obviously this can be anything you want, as long as it is unique $_SESSION['token'] = md5(session_id() . time()); ?> <form action="foo.php" method="post"> <input type="hidden" name="token" value="<?php echo $_SESSION['token'] ?>" /> <input type="text" name="bar" /> <input type="submit" value="Save" /> </form> // foo.php if (isset($_SESSION['token'])) { if (isset($_POST['token'])) { if ($_POST['token'] != $_SESSION['token']) { // double submit } } } 

Используйте уникальный токен с сообщением, чтобы каждый пост / postback обрабатывался только один раз.

Отключение кнопки отправки не очень хорошее решение, так как люди могут отключить javascript или делать другие странные вещи. Валидация на стороне клиента – это хороший старт, но он всегда должен быть скопирован с обработкой на стороне сервера.

Создайте уникальный одноразовый ключ для отправки с помощью формы.

Опираясь на Javascript – это плохая идея, потому что он может быть отключен пользователем. С помощью ключевой схемы, когда получение получено сервером, отправка для этого ключа может быть заблокирована. Вы можете ответить на дубликаты сообщений, как вам нравится.

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

Предотвращение повторной подачи формы показывает способ сделать это без javascript.

Отключите кнопку отправки с помощью Javascript после отправки формы ( onsubmit ).

Обратите внимание: если пользователь отключил Javascript, он все равно может отправить два раза. Является ли это достаточно часто, чтобы оправдать и проверку вашего кода (как вы сказали в своем вопросе), зависит от вас.

В качестве альтернативы используйте одноразовые ключи формы.

Я использую это:

 $form_token = $_SESSION['form_token'] = md5(uniqid()); 

отправьте $ form_token с формой, затем …

Я проверяю form_token:

 if($_SESSION['form_token'] != $_POST['form_token']) { echo 'Error'; } 

отключите кнопку отправки, как только пользователь отправит форму, используя JavaScript. Это то, что, например, StackOverflow использует, когда вы отвечаете на вопрос.

Например

 <input type="submit" onclick="this.disabled=true" /> 

Нажатие кнопки submit в два раза редко приводит к нескольким вставкам, но если вы хотите получить мертвое простое решение, используйте

 onsubmit="document.getElementById('submit').disabled = true" 

в теге формы, при условии, что вы передадите свою кнопку отправки id="submit"

Используйте JavaScript, чтобы отключить кнопку, как только она будет нажата.

 onclick="this.disabled=true;forms[0].submit();" 

Другой способ создать страницу подтверждения, где пользователь может, наконец, нажать кнопку отправки. Это может уменьшить возможности такого рода.

Aron Rotteveel Включает в себя уникальный токен на каждом POST для меня. Однако моя форма по-прежнему отправляется, когда пользователь обновляет страницу (F5). Мне удалось решить эту проблему, добавив сброс:

  // reset session token $_SESSION['token'] = md5( $_POST['token'] . time() ); 

мои заключительные сценарии:

 if (isset($_SESSION['token'])) { if (isset($_POST['token'])) { if ($_POST['token'] != $_SESSION['token']) { echo '<h3>Oops! You already submitted this request.</h3>'; } else { // process form // reset session token $_SESSION['token'] = md5( $_POST['token'] . time() ); } } else { echo 'post token not set'; $_SESSION['token'] = md5( $somevariable . time() ); } } 

ой! не забудьте добавить session_start(); перед <!DOCTYPE>

Я новичок в PHP, поэтому, пожалуйста, исправьте меня, если вы обнаружите нарушения.

Используйте JavaScript, чтобы остановить его отправку