我有一个简单的表单,可以将文本提交到我的SQL表中。问题是,在用户提交文本后,他们可以刷新页面,数据就会再次提交,而不必再次填写表单。我可以在文本提交后将用户重定向到另一个页面,但我希望用户留在同一页。
我记得读过一些关于为每个用户提供唯一会话ID并将其与另一个值进行比较以解决我的问题的内容,但我忘记了它在哪里。
我有一个简单的表单,可以将文本提交到我的SQL表中。问题是,在用户提交文本后,他们可以刷新页面,数据就会再次提交,而不必再次填写表单。我可以在文本提交后将用户重定向到另一个页面,但我希望用户留在同一页。
我记得读过一些关于为每个用户提供唯一会话ID并将其与另一个值进行比较以解决我的问题的内容,但我忘记了它在哪里。
我还想指出,你可以使用 JavaScript 方法 window.history.replaceState
来防止在刷新和返回按钮上重新提交。
<script>
if ( window.history.replaceState ) {
window.history.replaceState( null, null, window.location.href );
}
</script>
概念证明在这里:https://dtbaker.net/files/prevent-post-resubmit.php(链接已失效)
我仍然建议采用Post/Redirect/Get方法,但这是一种新颖的JS解决方案。
使用Post/Redirect/Get模式。http://en.wikipedia.org/wiki/Post/Redirect/Get
在我的网站上,我将把消息存储在cookie或session中,在提交后进行重定向,读取cookie/session,然后清除该会话或cookie变量的值。
您可以通过使用会话变量来防止表单重复提交。
首先,您需要在文本框中设置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()
开始会话。
<input type="hidden" name="randcheck" id="randcheck" value="<?php echo microtime(); ?>" />
来替代。 - Nikolay Bronskiy$_POST
之后,同一页重新加载以重置会话和POST变量。此外,变量的创建应在检查变量是否匹配之后进行。因此,不需要使用unset
。 - Hmerman6006rand()
并覆盖会话值,这意味着旧标签打开后将不再有效。有什么建议吗? - NcXNaV$_SESSION['specificform']['rand']
。 - undefinedif ( window.history.replaceState ) {
window.history.replaceState( null, null, window.location.href );
}
只需将此行代码放置在您的文件页脚处,即可看到神奇效果。
你应该真的使用Post-Redirect-Get模式来处理这个问题,但如果你以某种方式处于PRG不可行的位置(例如表单本身在一个包含文件中,阻止了重定向),你可以哈希一些请求参数以创建基于内容的字符串,然后检查你是否已经发送过它。
//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!
}
... process complete....
header('Location: thankyou.php');
您还可以将页面重定向到相同的页面。
如果您正在处理像评论这样的内容,并且希望用户留在同一页上,则可以使用Ajax来处理表单提交。
我找到了一个解决方法。您可以通过操作history
对象,在处理完POST
请求后避免重定向。
因此,您有以下HTML表单:
<form method=POST action='/process.php'>
<input type=submit value=OK>
</form>
当你在服务器上处理这个表单时,你可以通过设置 Location
头信息来重定向用户到 /the/result/page
,如下所示:
$cat process.php
<?php
process POST data here
...
header('Location: /the/result/page');
exit();
?>
处理完POST
的数据后,您会渲染一个小 <script>
和结果页面/the/result/page
<?php
process POST data here
render the <script> // see below
render `/the/result/page` // OK
?>
你应该渲染的<script>
:
<script>
window.onload = function() {
history.replaceState("", "", "/the/result/page");
}
</script>
结果为:
可以看到表单数据被POST
到process.php
脚本。
此脚本使用以下方式处理POST
的数据并立即渲染/the/result/page
:
POST
数据POST
更新
作为另一种解决方案,我请求Mozilla FireFox团队提供一个功能来允许用户设置NextPage
头文件,它将像Location
头文件一样工作,并使post/redirect/get
模式过时。
简而言之。服务器成功处理表单POST
数据时,它将:
NextPage
头而不是Location
头post/redirect/get
模式呈现处理POST
表单数据的结果,就像呈现GET
请求一样浏览器反过来当看到NextPage
头时:
NextPage
值调整window.location
NextPage
协商GET
请求而不是重新POST
表单数据如果实现了这一点,那会很棒,对吧? =)
使用 header 函数重定向页面。
header("Location:your_page.php");
可以将页面重定向到同一页面或不同页面。
插入数据到数据库后,使用 unset 函数清除 $_POST 变量。
unset($_POST);
unset
的原因是什么?请在您的回答中添加一些解释,以便其他人可以从中学习。 - Nico Haase<input type='hidden' name='post_id' value='".createPassword(64)."'>
然后在你的代码中这样做:
if( ($_SESSION['post_id'] != $_POST['post_id']) )
{
$_SESSION['post_id'] = $_POST['post_id'];
//do post stuff
} else {
//normal display
}
function createPassword($length)
{
$chars = "abcdefghijkmnopqrstuvwxyz023456789";
srand((double)microtime()*1000000);
$i = 0;
$pass = '' ;
while ($i <= ($length - 1)) {
$num = rand() % 33;
$tmp = substr($chars, $num, 1);
$pass = $pass . $tmp;
$i++;
}
return $pass;
}
Moob的帖子的优化版本。创建POST的哈希值,将其保存为会话cookie,并在每个会话中比较哈希值。
// Optionally Disable browser caching on "Back"
header( 'Cache-Control: no-store, no-cache, must-revalidate' );
header( 'Expires: Sun, 1 Jan 2000 12:00:00 GMT' );
header( 'Last-Modified: ' . gmdate('D, d M Y H:i:s') . 'GMT' );
$post_hash = md5( json_encode( $_POST ) );
if( session_start() )
{
$post_resubmitted = isset( $_SESSION[ 'post_hash' ] ) && $_SESSION[ 'post_hash' ] == $post_hash;
$_SESSION[ 'post_hash' ] = $post_hash;
session_write_close();
}
else
{
$post_resubmitted = false;
}
if ( $post_resubmitted ) {
// POST was resubmitted
}
else
{
// POST was submitted normally
}
POST
请求,查询字符串中没有任何内容,因此我使用Location: https://domain/same_script_path
... - 并且我仍然停留在相同的页面,只是没有表单数据。 - Ricky Levi