我有一个向SQL表提交文本的简单表单。问题在于,在用户提交文本之后,他们可以刷新页面并再次提交数据,而无需再次填写表单。我可以在文本提交后将用户重定向到另一个页面,但我希望用户停留在同一页面上。

我记得我读过一些关于给每个用户一个唯一的会话id,并将其与另一个值进行比较,这解决了我所遇到的问题,但我忘记了它在哪里。


当前回答

为什么不直接使用$_POST['submit']变量作为逻辑语句来保存表单中的任何内容呢?你总是可以重定向到相同的页面(以防它们刷新,当它们在浏览器中点击返回时,submit post变量将不再被设置。只要确保你的提交按钮有一个名称和id提交。

其他回答

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
}

我还想指出,您可以使用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解决方案。

使用Keverw answer的Post/Redirect/Get模式是个好主意。然而,你不能留在你的页面上(我认为这是你所要求的?)此外,它有时可能会失败:

如果web用户在首次提交完成之前刷新 由于服务器延迟,导致重复的HTTP POST请求在 某些用户代理。

另一个选择是存储在会话中,如果文本应该像这样写入SQL数据库:

if($_SERVER['REQUEST_METHOD'] != 'POST')
{
  $_SESSION['writeSQL'] = true;
}
else
{
  if(isset($_SESSION['writeSQL']) && $_SESSION['writeSQL'])
  {
    $_SESSION['writeSQL'] = false;

    /* save $_POST values into SQL */
  }
}

您可以通过会话变量防止表单重新提交。

首先,你必须在文本框中设置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()的每个文件上都启动会话。

你真的应该使用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!
    }