[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Защита формы от повторной отправки подробно
Raymond
Ниже идет ряд моих заблуждений по поводу пресечения повторной отправки POST,, которые я для себя записал , гуляя по разным форумам.
Они наверное выглядят смешно, поэтому я и хочу разобраться окончательно.
PAMAGITI :))

==================================================================================================== ========
Вот тут https://habrahabr.ru/post/86280/ один человек в самом конце пишет, что можно просто создать на странице формы токен (не уникальный), а в скрипте-обработчике его уничтожить

То есть:

* Страница формы:

$_SESSION['token'] = true;
//html-код формы

* Скрипт-обработчик:
if(isset($_POST['submit'])){
if(isset($_SESSION['token']) && $_SESSION['token'] === true){
//обрабатываем форму
unset($_SESSION['token']);
}
else{
//Выдаем ошибку о повторной отправке
}
}


Это решение не подходит.

Допустим если пользователь отправит форму, попадет на страницу обработчика, останется там. Токен удален , и при обновлении страницы повторная ообработка данных происходить не будет. Вроде все нормально. Но.
Теперь он откроет другую вкладку, попадет на страницу с форммой, тем самым создаст токен опять. Перейдя на страницу обработчика иобновив ее, он сможет отправить данные повторно, т.к. if(isset($_SESSION['token']) && $_SESSION['token'] === true) даст true.
Короче, метод не рабочий.

======================================================
======================================================
Метод 2 - уникальный ключ для формы.

Суть:

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

Например так:
* Страница с форммой:
<?php
session_start();
$_SESSION['token'] = уникальное значение;
?>

<form method = 'POST' action = 'script.php'>
<
input type = 'text' name = 'user_name'/>
<
input type = 'hidden' name = 'token' value = '<php echo $_SESSION['token']; ?>' />
<
input type = 'submit' name = 'submit'/>

* Скрипт-обработчик:

<?php
session_start();

if(isset($_POST['submit'])){
if($_SESSION['token'] === $_POST['token']){
//обрабатываем форму
$_SESSION['token'] = новое уникальное значение;
}
else{
//Выдаем ошибку о повторной отправке
}

?>


Гарантированная защита . Но есть проблема, и она серьезная:

Если пользователь открыл страницу формы, то у него создался уникальный ключ и приделался к форме. Он заполняет ее, может быть долго и муторно. Затем, не отправляя, по какой-то причине открывает такую же страницу в другой вкладке. Теперь у него обновился ключ сессии, и старый устарел. Он пытается отправить форму, которую заполнял на первой вкладке и получает ошибку,
т.к. токен из формы вкладки 1 не совпадает с новым.


тут https://phpclub.ru/talk/threads/Защита-форм...отправки.83304/
fixxer предлагает (пост N 11) создать массив ключей в сессии.
проблема , как я понял, будет в том, что придется держать в сессии большое количество данных. Особенно если ключи будут длинные
Ну и если количество открытых юзером вкладок страницы с формой превысит лимит размера массива, то форма первой из вкладок все-таки не пройдет проверку.

тут http://phpforum.su/index.php?showtopic=92222&st=0 AllesKlar, предлагает вот что:
if(!empty($_POST)) {
$_SESSION['POST'] = $_POST;
header('location: form_handler.php');
exit;
}

//form_handler.php
if(empty($_SESSION['POST'])) {
exit;
}

$post_data = $_SESSION['POST'];
$_SESSION['POST'] = array();

Минус (наверное) в том, что на время работы обработчика сессия будет забита POST-данными, и если их размер очень большой, то сильно забита.

==================================================================================================== ========
Еще один метод - тупо редирект. Безо всяких ключей и тд.
Суть:

Получаем POST данные в скрипте-обработчике, обрабатываем, а потом делаем редирект на другую страницу. Таким образом, POS-массив очищается и все, проблема решена. Но вот, что пишут тут https://habrahabr.ru/post/86280/#comment_2579959

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

==================================================================================================== ========
Пожалуй, самый лег вариант - это отправка формы через ajax. Там вопрос повторной оправки не стоит вообще.
Но это подходит не всегда. Мало ли у кого отключен JS


Чувствую себя умственно отсталым, и наверное это не просто так...
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.