формы — PHP предотвращает повторную отправку кэшированной кнопки назад без JavaScript

У меня есть форма, где пользователь вводит данные и представляет их себе. В моем коде я обрабатываю эти данные, а затем снова выполняю перенаправление на себя, чтобы предотвратить повторное повторное представление (я не использую PRG, потому что URL может быть добавлен в закладки).

простой пример (index.php):

<?php
if (isset($_POST["submitted"])) {
// do data processing

header("location:index.php?success=1");
die();
}
?>

<form action="#" method="post">
<p><input type="text" name="foo"></p>
<p><input type="submit" name="submitted"></p>
</form>

В отличие от таких вопросов, как этот (Запрет повторной отправки формы при нажатии кнопки назад), моя проблема не в том, что нажатие кнопки «Назад» запрашивает повторную отправку. Моя проблема в том, что когда я нажимаю назад, браузер (в частности, Chrome) кэширует входные данные и отображает их. Из-за этого пользователь может нажать кнопку «Отправить» еще раз, чтобы спамить мой сайт / делать дубликаты.

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

Я мог бы, вероятно, использовать AJAX для решения этой проблемы (Предотвращение повторной подачи формы), но я не могу придумать способ «изящно ухудшить», если javascript отключен («вы не можете отправить, потому что у вас не включен javascript, извините»: D).

Как я могу решить эту проблему?

2

Решение

Установите заголовки без кэширования на странице формы:

<?php
if (isset($_POST["submitted"]))
{
// do data processing
header("Location: index.php?success=1");
die();
}
else
{
header('Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0');
header('Pragma: no-cache');
}
?>

<form action="#" method="post">
<p><input type="text" name="foo"></p>
<p><input type="submit" name="submitted"></p>
</form>

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

2

Другие решения

Если повторная отправка при возврате пользователя является вашей основной проблемой, тогда следуйте шаблону PRG. Но убедитесь, что вы не смешиваете страницу для просмотра и отправки обработчика. Смешивать это — плохая идея, вопреки правилу принципа единой ответственности. Я не думаю, что URL может быть добавлен в закладки, будет проблемой, когда вы будете следовать шаблону PRG, если вы все равно не покажете что-то пользователю в обработчике сообщений (например, отображаете сообщение об успехе), тогда вы на самом деле не будете следовать шаблону PRG.

Но если вам все еще нравится смешивать их оба, @developerwjk должен решить проблему. Другой подход, вы можете создать уникальный токен для каждого сообщения (через скрытый ввод). Затем обработчик сообщения должен проверить, был ли этот токен кем-то предоставлен или нет. Поместить уникальный токен в сессию — это хорошо, так что вы можете проверить его позже. Убедитесь, что вы установили срок действия сессии. Это не должно привести к повторной отправке повторяющихся данных.

0