Лучший способ избежать отправки из-за обновления страницы
Я думаю, что эта проблема часто возникает в веб-приложении. Но я подробно расскажу о своих проблемах.
Я хотел бы знать, как избавиться от этого поведения, например, когда у меня есть такой код:
<?
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>
Когда я отправляю форму, я вставляю данные в базу данных, и получаю сообщение Operation Done. Затем, если я обновляю страницу, данные снова будут загружены.
Как я могу избежать этой ситуации? Любые предложения будут хорошими:)
Ответы
Ответ 1
Не показывать ответ после вашего действия; перенаправлять на другую страницу после завершения действия. Если кто-то обновляется, они обновляют запрашиваемую страницу GET, на которую вы перенаправили.
// submit
// set success flash message (you are using a framework, right?)
header('Location: /path/to/record');
exit;
Ответ 2
Задайте случайное число в сеансе, когда отображается форма, а также поместите это число в скрытое поле. Если номер и номер сеанса совпадают, удалите сеанс, запустите запрос; если они этого не делают, повторно отобразите форму и создайте новый номер сеанса. Это основная идея токенов 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
Вот так:
<?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>
Ответ 4
Я думаю, что это проще,
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>
Ответ 5
Я рассмотрел использование переменных сеанса, как предлагали другие, но может быть больно, когда переменная сеанса очищается из-за таймаута. Затем в моем приложении мне пришло, что для моих целей было гораздо более простое решение. Избавьтесь от проблемы, а не проверяйте ее. Решение ниже, как правило, работает для меня, потому что я обычно обрабатываю весь свой php, прежде чем сбрасывать его в my <html> ... </html> .
<?php
// PROCESS STUFF FOR YOUR PAGE HOWEVER YOU LIKE
// SAVE BACKUP COPIES OF _REQEUST _POST & _GET VARS IF NECESSARY FOR SOME REASON
$SAVED_REQUEST = $_REQEUST;
$SAVED_POST = $_POST;
$SAVED_GET = $_GET;
// FINALLY, IN YOUR LAST LINE ERASE THE PROBLEM VARIABLES...
$_REQUEST = $_POST = $_GET = NULL;
?>
<html>
<!-- PUT YOUR HTML HERE, ECHOING VARIABLES THAT WERE PROCESSES ABOVE -->
</html>
Это работает только потому, что я обычно делаю так, чтобы как можно больше отделить мой php от моего html. Очевидно, что он не может быть полностью разделен, но "разделение" делает мое решение возможным и упрощает чтение обоих php, поскольку все это в одном месте, и это упрощает чтение HTML-кода, потому что это не так как разбито с кодом.
Я думаю, вы могли бы теоретически просто поставить следующее в конце своей страницы.
<?php $_REQUEST = $_POST = $_GET = NULL; ?>
Ответ 6
Итак, для чего мне нужно, это то, что работает.
Основываясь на всех вышеперечисленных решениях, это позволяет мне перейти от формы к другой форме и к форме 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;
?>
Ответ 7
Мы работаем над веб-приложениями, где мы создаем количество php-форм. Это чертовски написать другую страницу, чтобы получить данные и отправить их для каждой формы. Чтобы избежать повторного представления, в каждой таблице мы создали поле "random_check", которое помечено как "Уникальное".
Загрузка на страницу генерирует случайное значение и сохраняет его в текстовом поле (которое явно скрыто).
В SUBMIT сохраните это случайное текстовое значение в поле "random_check" в вашей таблице. В случае запроса повторной подачи через ошибку, поскольку он не может вставить дублирующее значение.
После этого вы можете отобразить ошибку, например
if ( !$result ) {
die( '<script>alertify.alert("Error while saving data OR you are resubmitting the form.");</script>' );
}
Ответ 8
Не нужно перенаправлять...
замените 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>
Ответ 9
Это происходит из-за простого обновления, он снова отправит ваш запрос.
Итак, идея решить эту проблему, вылечив ее корень причины.
Я имею в виду, что мы можем настроить одну переменную сеанса внутри формы и проверить ее при обновлении.
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"]);">