admin / 14.10.2018

Подтвердите повторную отправку формы

.

Отправить заново

Допустим, мы делаем скрипт, который принимает данные из формы, переданные методом POST. Скрипт данные принял, обработал и выдал страницу с результатом. Но если пользователь вздумает обновить страницу в этот момент — он увидит сообщение такого плана:

Чтобы отобразить эту страницу, Firefox должен отправить информацию, которая повторит любое ранее произведённое действие (например, запрос на поиск или онлайн-покупка).

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

Для начала, покажу скрипт, который мы будем дорабатывать.

Можете отправить форму один раз, а потом нажать Ctrl+R и увидеть злополучное окно. Давайте от него избавляться.

Но сперва слово спонсору поста — сайту с полезным контентом для телефонов Samsung, который предлагает темы для samsung gt s5230, обои и прочий стафф.

Предотвращение повторной отправки формы с помощью серверного редиректа

Чтобы предотвратить повторную отправку данных формы можно делать серверный редирект. Это делается путем посылки браузеру заголовка Location с нужным урл. Например, это должна быть страница с благодарностью за заполненную форму. Тогда мы напишем что-то в духе:

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

Недостаток этого метода состоит в том, что пользователь может нажать кнопку «Назад» и вернуться на страницу с редиректом. Она снова швырнет его вперед и так пользователь с трудом сможет вернуться на две страницы назад, к форме, которую изначально заоплнял.

Предотвращение повторной отправки формы с помощью клиентского редиректа

Клиентский редирект называется клиентским потому что он происходит на стороне клиента. То есть в браузере. Клиентский редирект может происходить при помощи JavaScript и meta-тегов.

У JavaScript есть преимущество — он перезаписывает History браузера так, что даже если пользователь нажмет кнопку «Назад» браузера, он не вернется на страницу, которую отдал обработчик формы. То есть, окошко исчезнет капитально. Но JS у некоторых отключен.

У META-тегов, с другой стороны, есть преимущество в плане универсальности. Они редиректят всех и всегда.

Оптимально будет сочетать эти два способа. Как — описал Александр Шуркаев в заметке оптимальный редирект.

Используем его метод следующим образом.

Подтвердите повторную отправку формы?

Пробуем! Теперь, как видно, никакого окна не появляется. Что мы сделали? Мы проверили. Если данные пришли — мы выводим все необходимое для редиректа. В принципе, после этого уже можно даже делать exit, чтобы не грузить браузер лишними данными, которые все равно никто не увидит.

Понравилась статья? Поставь плюс один!

Теги: phpразработка

← Предыдущая статьяСледующая статья →

Способы защиты от повторной отправки формы при перезагрузке страницы

После отправки данных формы и их обработки серверным скриптом, необходимо предпринять меры по защите от повторной отправки данных во избежании нежелательных дублей записей в базе данных и писем на почте. Давайте рассмотрим два простых способа защиты форм от повторной отправки данных.

Все начинается с того, что пользователь заполняет ту или иную html форму на вашем сайте, после чего, когда все ее поля заполнены, он отправляет данные на сервер, нажимая кнопку «Отправить», «Оформить заказ», «Купить» и т. д. Причем отправка данных формы на сервер может производиться двумя способами — GET и POST.

GET-данные – незашифрованные данные, которые передаются прямо через адресную строку, добавляя соответственные переменные к адресу текущей страницы, например, https://yandex.ru/search/?text=example. Как видно из примера — к основному адресу добавляется параметр text, значение которого и есть поисковый запрос, который вы отправляете через форму поиска на сервер Яндекса.

POST-данные – зашифрованные данные, которые не видны в адресной строке и ссылку на них дать нельзя. Однако есть одна небольшая проблема — при обновлении страницы, сразу после отправки POST-данных, любой из известных на данный момент браузеров заботливо переспросит у вас — «Чтобы отобразить эту страницу, Firefox должен отправить информацию, которая повторит любое ранее произведённое действие (например, запрос на поиск или онлайн-покупка)». Такой вопрос вам задаст Файерфокс, если сразу после отправки POST-данных нажать кнопку F5 или обновить страницу каким-то другим способом, например, используя специальную кнопку в панели инструментов браузера.

Подтвердите повторную отправку формы

Другие браузеры спросят то же самое, только другими словами.

Конечно не многие пользователи обновляют страницу сразу после отправки данных формы (казалось бы, зачем вообще это делать), но иногда такая же проблема может возникнуть при нажатии кнопки «Назад». Если переход будет осуществляться на страницу, с которой отправлялись данные формы, она не загрузится, а вместо этого на экране появится сообщение о том, что данные устарели или что-то в этом роде.

Проблема повторной отправки данных форм актуальна в тех случаях, когда сразу после, происходит добавление новой строки в базу данных, например, заказ в интернет-магазине, регистрация нового пользователя и т. д., а также отправляется соответствующее email-уведомление. Для того, чтобы избежать нежелательных дублей записей в базе данных и писем на почте, необходимо предотвращать повторную отправку данных. А если сказать точнее — предотвращать или игнорировать. Поэтому мы рассмотрим два основных способа:

Способ №1: «Переадресация» — предотвращение повторной отправки данных

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

Итак, в том месте скрипта, где у вас происходит запись новой строки в базу данных или отправка уведомления на электронную почту, нужно добавить следующий код:

header(‘Location: http://’.$_SERVER[‘HTTP_HOST’].$_SERVER[‘REQUEST_URI’].’?success’); exit();

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

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

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

Способ №2: «Сессия» — игнорирование данных, отправленных повторно

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

Суть метода — к целевой форме нужно добавить дополнительное скрытое поле с произвольным именем и с произвольным значением, например так:

<input type=’hidden’ name=’sessid’ value='<?=$_SESSION[‘sessid’]?>’>

Предварительно, разумеется, нужно зарегистрировать сессию с идентификатором sessid и присвоить ей как можно более абстрактное значение при помощи одной из хеш-функций, например MD5.

/* сама функция генерации абстрактного хеша */ function setRandomSessid() { $_SESSION[‘sessid’] = md5(date(‘d.m.Y H:i:s’).rand(1, 1000000)); } /* создаем сессию в начале скрипта */ setRandomSessid();

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

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

setRandomSessid();

Теперь нам осталось только сверить сессию sessid со скрытым значением одноименного поля sessid, переданным нашей с вами формой. Если они идентичны, то есть смысл проверять остальные данные, а если нет — форму попытались отправить заново, при этом сама сессия переопределилась, а значение sessid, которое передавалось через форму осталось старым.

if(isset($_POST) && $_POST[‘sessid’] == $_SESSION[‘sessid’]) { /* только в этом случае приступаем к проверке данных формы */ }

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

Как видите, все очень просто — мы с вами разобрали два простых способа повторной отправки данных формы. Оба прекрасно работают, хорошо себя зарекомендовали и неоднократно проверялись на практике на разных сайтах. Но на наш взгляд, предпочтительней все-таки использовать второй способ с сессией.

.

FILED UNDER : IT

Submit a Comment

Must be required * marked fields.

:*
:*