Использование хэша для проверки обновления страницы со значениями $ _POST - PullRequest
3 голосов
/ 16 апреля 2010

При публикации формы на той же странице 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...

Что-то не так с этим решением?

ОБНОВЛЕНИЕ: Примером этого сценария будет вставка строки в таблицу регистрации. Вы бы хотели, чтобы эта операция выполнялась один раз.

Ответы [ 3 ]

2 голосов
/ 16 апреля 2010

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

<?php
    $token = /* a randomly generated string */;
    $_SESSION['_token'] = $token;
?>
<input type="hidden" name="_token" value="<?php echo $token; ?>" />

После каждой отправки вы аннулируете токен сеанса. Если токен в сеансе отличается от токена, отправленного с формой, вы можете удалить POST.

Комментарий: вы можете сделать это для каждого элемента. Например, здесь, в SO, у вас может быть открыто несколько окон вопросов и вы можете ответить на несколько вопросов одновременно. Вы можете создать токен для каждого вопроса, чтобы пользователь мог иметь несколько действительных токенов одновременно, но только один на вопрос.

Примером этого сценария будет вставка строки в таблицу регистрации. Вы бы хотели, чтобы эта операция выполнялась один раз.

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

1 голос
/ 16 апреля 2010

Использование токенов в сочетании с шаблоном POST / REDIRECT / GET представляется наилучшим доступным решением.

  • Установка одноразового токена не позволит пользователю нажать кнопку «Назад» и снова попытаться отправить форму.
  • Перенаправление пользователя и использование представления для отображения ввода позволяет ему нажимать кнопку «Обновить», если они пожелают.
1 голос
/ 16 апреля 2010

Я обычно предпочитаю, чтобы обработчик POST делал все, что ему нужно, а затем перенаправлял пользователя на новую страницу с помощью

header("Location: new-page.php");

чтобы они могли обновиться, ничего не испортив

...