Лучший способ избежать отправки из-за обновления страницы - PullRequest
21 голосов
/ 17 апреля 2011

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

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

<?
    if (isset($_POST['name'])) {
        ... operation on database, like to insert $_POST['name'] in a table ...
        echo "Operation Done";
        die();
    }

?>

<form action='page.php' method='post' name="myForm">
    <input type="text" maxlength="50" name="name" class="input400" />
    <input type="submit" name="Submit" />
</form>

Когда форма отправляется, данные вставляются в базу данных и выдается сообщение Операция выполнена . Затем, если я обновлю страницу, данные снова будут вставлены в базу данных.

Как этой проблемы можно избежать? Любое предложение будет оценено по достоинству:)

Ответы [ 10 ]

35 голосов
/ 17 апреля 2011

Не показывать ответ после действия создания;перенаправить на другую страницу после завершения действия.Если кто-то обновляется, он обновляет страницу запроса GET, на которую вы перенаправлены.

// submit
// set success flash message (you are using a framework, right?)
header('Location: /path/to/record');
exit;
25 голосов
/ 17 апреля 2011

Установите случайное число в сеансе при отображении формы, а также поместите это число в скрытое поле.Если опубликованный номер и номер сеанса совпадают, удалите сеанс, выполните запрос;если они этого не делают, повторно отобразите форму и сгенерируйте новый номер сеанса.Это основная идея токенов XSRF, вы можете прочитать больше о них и их использовании для безопасности здесь: http://en.wikipedia.org/wiki/Cross-site_request_forgery

Вот пример:

<?php
session_start();

if (isset($_POST['formid']) && isset($_SESSION['formid']) && $_POST["formid"] == $_SESSION["formid"])
{
    $_SESSION["formid"] = '';
    echo 'Process form';
}
else
{
    $_SESSION["formid"] = md5(rand(0,10000000));
?>
    <form action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>" method="post">
    <input type="hidden" name="formid" value="<?php echo htmlspecialchars($_SESSION["formid"]); ?>" />
    <input type="submit" name="submit" />
</form>
<?php } ?>
3 голосов
/ 17 апреля 2011

Как это:

<?php
if(isset($_POST['uniqid']) AND $_POST['uniqid'] == $_SESSION['uniqid']){
    // can't submit again
}
else{
    // submit!
    $_SESSION['uniqid'] = $_POST['uniqid'];
}
?>

<form action="page.php" method="post" name="myForm">
    <input type="hidden" name="uniqid" value="<?php echo uniqid();?>" />
    <!-- the rest of the fields here -->
</form>
2 голосов
/ 21 февраля 2019

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

При успешной отправке формы включите этот бит Javascript на странице:

<script>history.pushState({}, "", "")</script>

Это выдвигаеттекущий URL на стек истории.Поскольку это новый элемент в истории, обновление не будет повторно отправлено.

1 голос
/ 09 ноября 2012

Я думаю, что это проще,

page.php

<?php
   session_start();
   if (isset($_POST['name'])) {
        ... operation on database, like to insert $_POST['name'] in a table ...
        $_SESSION["message"]="Operation Done";
        header("Location:page.php");
        exit;
    }
?>

<html>
<body>
<div style='some styles'>
<?php
//message here
echo $_SESSION["message"];
?>
</div>
<form action='page.php' method='post'>
<!--elements-->
</form>
</body>
</html>
0 голосов
/ 07 марта 2019

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

$sample = $_POST['submit'];
if ($sample == "true") 
 {
//do it your code here
$sample = "false";
 }
0 голосов
/ 24 марта 2017

Это происходит потому, что просто при обновлении он снова отправит ваш запрос.

Так что идея решить эту проблему, вылечив корень причины.

Я имею в виду, что мы можем установить одну переменную сеанса внутри формы и проверить ее при обновлении.

if($_SESSION["csrf_token"] == $_POST['csrf_token'] )
{
// submit data  
}

//inside from 

$_SESSION["csrf_token"] = md5(rand(0,10000000)).time(); 

<input type="hidden" name="csrf_token" value=" 
htmlspecialchars($_SESSION["csrf_token"]);"> 
0 голосов
/ 19 февраля 2017

Нет необходимости перенаправлять ...

заменить die(); на

isset(! $_POST['name']);

, установив isset в значение isset, не равное $ _POST ['name'], поэтому, когда выобновите его, он больше не добавится в вашу базу данных, если вы снова не нажмете кнопку отправки.

<?
    if (isset($_POST['name'])) {
        ... operation on database, like to insert $_POST['name'] in a table ...
        echo "Operation Done";
        isset(! $_POST['name']);
    }

?>

<form action='page.php' method='post' name="myForm">
    <input type="text" maxlength="50" name="name" class="input400" />
    <input type="submit" name="Submit" />
</form>
0 голосов
/ 21 декабря 2016

Мы работаем над веб-приложениями, где разрабатываем несколько форм php. Это чертовски сложно написать еще одну страницу, чтобы получить данные и отправить их для каждой формы. Чтобы избежать повторной отправки, в каждой таблице мы создали поле random_check, помеченное как «Уникальное».

При загрузке страницы генерирует случайное значение и сохраняет его в текстовом поле (которое явно скрыто).

При SUBMIT сохраните это случайное текстовое значение в поле random_check в вашей таблице. В случае повторной подачи запроса произойдет ошибка, так как он не может вставить повторяющееся значение.

После этого вы можете отобразить ошибку как

if ( !$result ) {
        die( '<script>alertify.alert("Error while saving data OR you are resubmitting the form.");</script>' );
}
0 голосов
/ 30 апреля 2015

Итак, для того, что мне нужно, это то, что работает.

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

Спасибо тем, кто опубликовал свое решение, которое быстро привело меня к моему собственному.

<?php
//Check if there was a post
if ($_POST) {
//Assuming there was a post, was it identical as the last time?
   if (isset($_SESSION['pastData']) AND $_SESSION['pastData'] != $_POST) {
//No, Save
   } else {
//Yes, Don't save
   }
} else {
//Save
}
//Set the session to the most current post.
$_session['pastData'] = $_POST;
?>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...