我认为这个问题经常发生在Web应用程序开发上。但我会尝试详细解释我的问题。
我想知道如何纠正这种行为,例如,当我有这样的代码块时:
<?
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 。然后,如果我刷新页面,数据将再次插入数据库。
如何避免这个问题?任何建议将不胜感激:)
答案 0 :(得分:35)
创建操作后不要显示响应;相反,在操作完成后重定向到另一个页面。如果有人刷新,他们会刷新您重定向到的GET请求页面。
// submit
// set success flash message (you are using a framework, right?)
header('Location: /path/to/record');
exit;
答案 1 :(得分:25)
在显示表单时在会话中设置随机数,并将该数字放在隐藏字段中。如果发布的号码和会话号匹配,则删除会话,运行查询;如果他们不这样做,重新显示表单,并生成一个新的会话号码。这是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 } ?>
答案 2 :(得分: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>
答案 3 :(得分:1)
我认为这更简单,
<强> 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>
答案 4 :(得分:1)
我遇到了类似的问题。我需要向用户显示POST的结果。我不想使用会话,也不想使用URL中的结果进行重定向(这很安全,我不希望它被意外添加书签)。我找到了一个非常简单的解决方案,该解决方案适用于其他答案中提到的情况。
成功提交表单后,请在页面上添加以下Javascript:
<script>history.pushState({}, "", "")</script>
它将当前URL推送到历史记录堆栈中。由于这是历史上的新项目,因此刷新不会重新发布。
答案 5 :(得分:0)
我们在设计php表单数量的网络应用程序上工作。编写另一个页面以获取数据并为每个表单提交数据是很麻烦的。为避免重新提交,我们在每个表格中创建了一个“random_check”字段,该字段标记为“唯一”。
在页面加载时生成一个随机值并将其存储在文本字段中(显然是隐藏的)。
在SUBMIT上将此随机文本值保存在表格的“random_check”字段中。如果重新提交,查询将通过错误,因为它无法插入重复值。
之后您可以显示错误,如
if ( !$result ) {
die( '<script>alertify.alert("Error while saving data OR you are resubmitting the form.");</script>' );
}
答案 6 :(得分:0)
无需重定向...
用
替换die();
isset(! $_POST['name']);
,将isset设置为isset不等于$ _POST [&#39; name&#39;],因此当您刷新它时,它将不会再添加到您的数据库,除非您再次单击提交按钮。
<?
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>
答案 7 :(得分:0)
这是因为只需刷新它就会再次提交您的请求。
因此,通过治愈其根源来解决这个问题的想法。
我的意思是我们可以在表单中设置一个会话变量,并在更新时进行检查。
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"]);">
答案 8 :(得分:0)
我认为以下是避免重新提交或刷新页面的更好方法。
$sample = $_POST['submit'];
if ($sample == "true")
{
//do it your code here
$sample = "false";
}