При отправке формы на одну и ту же страницу PHP, какой правильный метод найти, если страница была случайно обновлена, а не отправлена снова?
Вот что я сейчас использую:
$tmp = implode('',$_POST); $myHash = md5($tmp); if(isset($_SESSION["myHash"]) && $_SESSION["myHash"] == $myHash) { header("Location: index.php"); // page refreshed, send user somewhere else die(); } else { $_SESSION["myHash"] = $myHash; } // continue processing...
Что-то не так с этим решением?
ОБНОВЛЕНИЕ: примером для этого сценария будет вставка строки в таблицу регистрации. Вы хотели бы, чтобы эта операция выполнялась один раз.
Начнем с того, что вы не можете отличить случайные обновления от целенаправленных обновлений. Таким образом, вы можете решить не разрешать обновления вообще, или, другими словами, требовать, чтобы каждая форма должна быть уникальной. Лучший способ сделать это – вставить произвольный токен в форму.
<?php $token = /* a randomly generated string */; $_SESSION['_token'] = $token; ?> <input type="hidden" name="_token" value="<?php echo $token; ?>" />
После каждой подачи вы аннулируете токен сеанса. Если токен в сеансе отличается от того, который представлен в форме, вы можете отменить POST.
Re comment: Вы можете сделать это по отдельности. Например, здесь, на SO, вы можете открыть несколько окон вопросов и сразу ответить на несколько вопросов. Вы можете сделать токен по каждому вопросу, поэтому пользователь может иметь несколько действительных токенов в любой момент времени, но только один вопрос.
Примером этого сценария будет вставка строки в регистрационную таблицу. Вы хотели бы, чтобы эта операция выполнялась один раз.
В этом случае вы, вероятно, не должны слишком беспокоиться о фактическом POST, но о согласованности данных как таковых. У каждого пользователя должна быть уникальная идентификация, например, его адрес электронной почты. Если адрес уже зарегистрирован в базе данных, вы не регистрируете пользователя снова. Это не зависит от того, почему пользователь пытался зарегистрироваться дважды (двойная отправка или фактическая попытка зарегистрироваться снова).
Обычно я предпочитаю, чтобы обработчик POST выполнял все, что ему нужно, а затем перенаправлял пользователя на новую страницу с помощью
header("Location: new-page.php");
так что они могут освежиться, не испортив ничего
Использование жетонов в сочетании с шаблоном проектирования POST / REDIRECT / GET представляется лучшим решением.