Как предотвратить множественную отправку форм при нескольких кликах в PHP
Используйте уникальный токен, создаваемый каждый раз, когда вы показываете форму и которая может использоваться только один раз; также полезно предотвращать атаки CSRF и повторного воспроизведения . Маленький пример:
<?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>
с<?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 .
Вы можете отключить кнопку после первого щелчка (используя JavaScript), а также проверить на внутреннем контенте (просто в случае, если они отключили свой JavaScript), который проверяет, были ли они недавно отправлены.
Существует несколько различных способов сделать проверку в фоновом режиме. Одним из способов было бы установить переменную сеанса, когда они нажмут на нее в первый раз, что может позволить системе знать, что она обрабатывает. Если они нажмут второй, третий или четвертый раз, тогда он может просто проверить переменную сеанса, и если это указывает на то, что она уже нажата, она не будет обрабатываться.
Это всего лишь один пример – вы можете использовать это как начало.
Вы могли бы добавить что-то вроде этого
<input type="hidden" name="form-token" value="someRandomNumber">
Затем в фоновом режиме у вас есть возможность идентифицировать несколько представлений форм. Разумеется, это решение имеет некоторый багаж, так как вы должны удалить формальные значки, которые, как вы знаете, закончили обработку и т. Д.
В большинстве случаев отключенная форма делает трюк, например, либо отключив кнопку, либо добавив return false
в событие отправки формы (не уверен, что это работает без jQuery, хотя).
Я рекомендую запретить кнопку отправки, потому что в случае временной сетевой проблемы (т. Е. Запрос не прошел вообще), если пользователь решает прервать отправку (клавиша Esc / Stop), он не может повторно отправить сообщение после того, как сеть служба была восстановлена, и вместо этого придется перезагрузить страницу и снова заполнить все записи формы.
Это самый коммонический ответ на вашу проблему
if (isset($_COOKIE['FormSubmitted'])) { die('You may only submit this form once per session!'); }