Подтвердить что ты не робот

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

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

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

4b9b3361

Ответ 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>
    
  • Используйте сеансы PHP для установки переменной сеанса (например $_SESSION ['posttimer']) на текущий timestamp on post. Перед тем, как обработать форму в 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
            }
        }
    }
    

Ответ 2

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

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

Ответ 3

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

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

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

Ответ 5

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

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

Ответ 6

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

Ответ 7

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

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

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

Я проверяю form_token:

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

Ответ 8

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

Например

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

Ответ 9

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

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

Ответ 10

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

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

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

Ответ 11

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

Ответ 12

Я делаю следующее на action.php

if($_SESSION && isset($_SESSION['already_submitted'])) {

  # If already submitted just redirect to thank you page

} else {

    # If first submit then assign session value and process the form
    $_SESSION['already_submitted'] = true;

    # Process form

}

Примечание. Всегда начинайте сеансы в заголовке с помощью session_start();

Ответ 13

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

            // 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, поэтому, пожалуйста, исправьте меня, если вы обнаружите нарушения.

Ответ 14

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