我有一个向SQL表提交文本的简单表单。问题在于,在用户提交文本之后,他们可以刷新页面并再次提交数据,而无需再次填写表单。我可以在文本提交后将用户重定向到另一个页面,但我希望用户停留在同一页面上。
我记得我读过一些关于给每个用户一个唯一的会话id,并将其与另一个值进行比较,这解决了我所遇到的问题,但我忘记了它在哪里。
我有一个向SQL表提交文本的简单表单。问题在于,在用户提交文本之后,他们可以刷新页面并再次提交数据,而无需再次填写表单。我可以在文本提交后将用户重定向到另一个页面,但我希望用户停留在同一页面上。
我记得我读过一些关于给每个用户一个唯一的会话id,并将其与另一个值进行比较,这解决了我所遇到的问题,但我忘记了它在哪里。
当前回答
基本上,你需要重定向出该页面,但它仍然可以使一个问题,而你的互联网缓慢(重定向头从服务器端)
基本场景示例:
点击提交按钮两次
解决方法
客户端 一旦客户端点击它,禁用提交按钮 如果你使用Jquery: Jquery.one PRG模式 服务器端 使用基于差分的哈希时间戳/发送请求时的时间戳。 Userequest令牌。当主进程加载完成时,分配一个临时请求标记,如果重复则忽略该标记。
其他回答
使用Post/Redirect/Get模式。http://en.wikipedia.org/wiki/Post/Redirect/Get
对于我的网站,我将在cookie或会话中存储消息,在发布后重定向,读取cookie/会话,然后清除该会话或cookie变量的值。
我找到了下一个变通办法。您可以通过操作历史对象在处理POST请求后转义重定向。
你有一个HTML表单
<form method=POST action='/process.php'>
<input type=submit value=OK>
</form>
当你在你的服务器上处理这个表单时,你不是重定向用户到/the/result/页面,而是像这样设置Location头:
$cat process.php
<?php
process POST data here
...
header('Location: /the/result/page');
exit();
?>
处理post数据后,呈现小的<脚本>和result/ the/result/page
<?php
process POST data here
render the <script> // see below
render `/the/result/page` // OK
?>
你应该渲染的<脚本>:
<script>
window.onload = function() {
history.replaceState("", "", "/the/result/page");
}
</script>
结果是:
如你所见,表单数据被post到process.php脚本。 这个脚本处理post数据并立即渲染/the/result/page:
没有重定向 当你刷新页面时没有rePOST数据(F5) 当你通过浏览器历史导航到上一页/下一页时,没有rePOST
UPD
作为另一个解决方案,我要求Mozilla FireFox团队允许用户设置NextPage头,它将像Location头一样工作,使post/redirect/get模式过时。
简而言之。当服务器处理表单POST数据成功时:
设置NextPage头而不是位置 呈现POST表单数据处理的结果,就像在POST /redirect/ GET模式中呈现GET请求一样
浏览器依次看到NextPage头:
调整窗口。位置与NextPage值 当用户刷新页面时,浏览器将协商GET请求NextPage而不是rePOST表单数据
我认为这将是极好的,如果实施,不是吗?=)
这个form.php示例展示了如何正确地使用PRG(当表单有效或无效时)。
它只在表单有效且执行操作时重定向到相同的页面。 重定向可以防止表单在页面刷新时被重新提交。 当表单有效时,它使用session来避免丢失想要显示的成功消息。 有两个测试按钮:“有效提交”,“无效提交”。两者都试一下,然后刷新页面。
<?php
session_start();
function doSelfRedirect()
{
header('Location:'.$_SERVER['PHP_SELF']);
exit;
}
function setFlashMessage($msg)
{
$_SESSION['message'] = $msg;
}
function getFlashMessage()
{
if (!empty($_SESSION['message'])) {
$msg = $_SESSION['message'];
unset($_SESSION['message']);
} else {
$msg = null;
}
return $msg;
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Validation primitive example.
if (empty($_POST['valid'])) {
$formIsValid = false;
setFlashMessage('Invalid form submit');
} else {
$formIsValid = true;
}
if ($formIsValid) {
// Perform any actions here.
// ...
// Cool!
setFlashMessage('Form is valid. Action performed.');
// Prevent form resubmission.
doSelfRedirect();
}
}
?>
<h1>Hello form</h1>
<?php if ($msg = getFlashMessage()): ?>
<div><?= $msg ?></div>
<?php endif; ?>
<form method="post">
<input type="text" name="foo" value="bar"><br><br>
<button type="submit" name="invalid" value="0">Invalid submit</button>
<button type="submit" name="valid" value="1">Valid submit</button>
</form>
你真的应该使用Post Redirect Get模式来处理这个问题,但如果你在某种程度上陷入了PRG不可行的境地(例如,表单本身在一个include中,防止重定向),你可以散列一些请求参数,根据内容生成一个字符串,然后检查你是否已经发送了它。
//create digest of the form submission:
$messageIdent = md5($_POST['name'] . $_POST['email'] . $_POST['phone'] . $_POST['comment']);
//and check it against the stored value:
$sessionMessageIdent = isset($_SESSION['messageIdent'])?$_SESSION['messageIdent']:'';
if($messageIdent!=$sessionMessageIdent){//if its different:
//save the session var:
$_SESSION['messageIdent'] = $messageIdent;
//and...
do_your_thang();
} else {
//you've sent this already!
}
您可以通过会话变量防止表单重新提交。
首先,你必须在文本框中设置rand(),并在表单页面上设置$_SESSION['rand']:
<form action="" method="post">
<?php
$rand=rand();
$_SESSION['rand']=$rand;
?>
<input type="hidden" value="<?php echo $rand; ?>" name="randcheck" />
Your Form's Other Field
<input type="submit" name="submitbtn" value="submit" />
</form>
在此之后,检查$_SESSION['rand']与文本框$_POST['randcheck']值 是这样的:
if(isset($_POST['submitbtn']) && $_POST['randcheck']==$_SESSION['rand'])
{
// Your code here
}
确保在使用session_start()的每个文件上都启动会话。