Иногда пользователь может дважды нажать Enter
, и сообщение будет вставлено дважды.
Есть ли решение предотвратить это, кроме как проверить, есть ли сообщение с тем же title
и content
?
Существует несколько решений этой проблемы:
Используйте 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>
Используйте сеансы 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(); }
Включите уникальный токен в каждом 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, чтобы остановить его отправку