Как предотвратить отправку нескольких форм в несколько кликов в PHP - PullRequest
16 голосов
/ 06 января 2011

Как запретить отправку нескольких форм в несколько кликов в PHP

Ответы [ 8 ]

36 голосов
/ 06 января 2011

Используйте уникальный токен, сгенерированный каждый раз при отображении формы и который можно использовать только один раз;он также полезен для предотвращения атак CSRF и replay .Небольшой пример:

<?php
session_start();

/**
 * Creates a token usable in a form
 * @return string
 */
function getToken(){
  $token = sha1(mt_rand());
  if(!isset($_SESSION['tokens'])){
    $_SESSION['tokens'] = array($token => 1);
  }
  else{
    $_SESSION['tokens'][$token] = 1;
  }
  return $token;
}

/**
 * Check if a token is valid. Removes it from the valid tokens list
 * @param string $token The token
 * @return bool
 */
function isTokenValid($token){
  if(!empty($_SESSION['tokens'][$token])){
    unset($_SESSION['tokens'][$token]);
    return true;
  }
  return false;
}

// Check if a form has been sent
$postedToken = filter_input(INPUT_POST, 'token');
if(!empty($postedToken)){
  if(isTokenValid($postedToken)){
    // Process form
  }
  else{
    // Do something about the error
  }
}

// Get a token for the form we're displaying
$token = getToken();
?>
<form method="post">
  <fieldset>
    <input type="hidden" name="token" value="<?php echo $token;?>"/>
    <!-- Add form content -->
  </fieldset>
</form>

Объедините его с перенаправлением, чтобы сохранить идеальное поведение вперед и назад.См. Шаблон POST / redirect / GET для получения дополнительной информации о перенаправлении.

6 голосов
/ 06 января 2011

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

Это только один пример - вы можете использоватьэто как начало.

3 голосов
/ 06 января 2011

Я рекомендую не отключать кнопку отправки, поскольку в случае временной проблемы с сетью (т. Е. Запрос вообще не прошел), если пользователь решает прервать отправку (клавиша Esc / кнопка «Стоп»), он не может отправитьснова, как только сетевая служба будет восстановлена, и вместо этого придется перезагрузить страницу и снова заполнить все записи формы.

1 голос
/ 06 января 2011

Вы можете добавить что-то вроде этого

<input type="hidden" name="form-token" value="someRandomNumber">

Затем на бэк-энде у вас есть способ сохранить несколько отправленных форм.Это решение, конечно, имеет некоторый багаж, так как вам нужно удалить токены форм, которые, как вы знаете, завершили обработку и т. Д.или добавив return false к событию отправки формы (хотя я не уверен, что это работает без jQuery).

0 голосов
/ 22 октября 2018

Вы также можете предотвратить это, используя уникальное поле, такое как адрес электронной почты / имя пользователя или регистрационный номер. Затем проверьте новое поле на соответствие существующему в БД, и, если оно совпадает, то пользователь уже зарегистрировался, и отправка формы должна прекратиться, в противном случае продолжить отправку формы.

0 голосов
/ 30 июля 2018

Я делаю следующее на 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 ();

0 голосов
/ 06 января 2018

Можете ли вы просто скрыть кнопку при нажатии? Это не повлияет на обработку формы (как я знаю, проблема заключается в немедленном отключении кнопки), но, по сути, будет делать то же самое. Если вы действительно беспокоитесь об этом, вы можете просто показать еще одну кнопку, которая на самом деле ничего не делает. Это может быть нетрадиционный обходной путь, но, тем не менее, обходной.

0 голосов
/ 27 декабря 2015

Это самый общий ответ на вашу проблему

if (isset($_COOKIE['FormSubmitted']))
{
    die('You may only submit this form once per session!');
}
...