PHP: Предотвратите случайную повторную обработку формы при нажатии кнопки "Назад"


Как лучше всего остановить повторную обработку формы, когда пользователь нажимает кнопку "Назад"?

Я следую шаблону Post/Redirect/Get, поэтому у меня нет проблем, если нажать клавишу F5, но кнопка "Назад" по-прежнему предоставляет возможность повторно отправить форму. Если эта форма является страницей обработки кредитной карты, это плохо.

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

У меня есть form.php который подчиняется самому себе. Если при отправке не было ошибок во входных данных, пользователь перенаправляется на form_thanks.php . Ответный удар (и "Отправить" или "Отправить повторно") после повторной отправки form.php (ПЛОХО!), а затем возвращает их к form_thanks.php .

Пожалуйста, также включите решения, которые не предполагают использования сеансов, если это возможно.

Author: Community, 2009-10-30

6 answers

Я бы сделал это по-другому. Поместите скрытый ввод со случайной строкой в качестве значения, и когда он будет отправлен, сохраните эту случайную строку в сеансе. Настройте простую проверку, чтобы убедиться, что они уже опубликовали ее, и если они не приняли ввод.

 7
Author: Whitey, 2009-10-29 23:07:16

Это должно быть сделано с помощью одноразового токена или nonce. php/сервер должен включить этот токен в скрытое поле формы.

Он должен хранить список всех последних токенов, и каждый раз при отправке формы он должен проверять, находится ли токен в списке последних действительных токенов.

Если этого нет в списке, не обрабатывайте форму повторно.
Если он есть в списке, то обработайте форму и удалите токен из списка.

Токены могут быть обрабатывается в сеансах или просто в простой таблице базы данных без сеансов. Однако токены должны быть специфичными для пользователя.

Это также рекомендуемый способ избежать CSRF атак.

 2
Author: philfreo, 2009-11-02 17:06:25

Просто размышляю здесь вслух. Но как насчет варианта отправки/перенаправления/получения, где окончательное получение на самом деле не является окончательным получением;) Но, скорее, он, в свою очередь, всегда автоматически переходит на действительно последнюю страницу, так что, если пользователь нажмет кнопку "Назад", он вернется туда, откуда пришел?

ИЗМЕНИТЬ:

Хорошо, принимая во внимание комментарий ОП, вот еще одна идея. URL-адрес для отправки формы может быть задан так, чтобы требовался параметр, который подходит только для одно применение. Этот токен будет сгенерирован (с использованием MD5 или чего-то подобного) до отправки формы и может быть сохранен в базе данных (в ответ на чье-то предложение вы запросили решение без использования сеансов). После обработки формы этот маркер будет помечен в базе данных как уже использованный. Чтобы при возврате на страницу с тем же маркером можно было предпринять шаги для предотвращения повторной отправки данных формы в серверную часть.

 1
Author: George Jempty, 2009-10-30 00:18:15

Поздний ответ, но можно было бы вообще избежать обработки, используя решение на основе AJAX; не было бы проблемы с включением nonce в эту схему обработки, но с использованием асинхронного запроса, который в случае успеха перенаправляет пользователя, запросы не повторяются путем обновления, нажатия назад или чего-либо другого, кроме нажатия кнопки.

Также легко реализовать механизм, который предотвращает двойное нажатие кнопки или ее "блокировку", если что-то произошло во время запроса путем встраивания в обработчик запроса (будь то высокий уровень с помощью PrototypeJS или jQuery или низкий уровень с помощью вашей функции, выполняемой вручную) механизмов включения и отключения кнопки при завершении запроса и первом срабатывании, соответственно.

 1
Author: Dereleased, 2009-11-17 20:58:25

Я нахожу, что возврат приведет форму в состояние, в котором она была до перенаправления страницы, если это так, есть скрытый ввод/переменная или что-то, что начинается со значения true, затем, как только форма будет отправлена, и если значение true, измените его на false, а затем отправьте, иначе верните false

 0
Author: Psytronic, 2009-10-29 22:06:31

Попробуйте это:

<SCRIPT type="text/javascript">
    window.history.forward();
</SCRIPT>
 -1
Author: zphp, 2012-10-02 08:01:12