Php 如何防止用户重新发送表单数据?

Php 如何防止用户重新发送表单数据?,php,forms,Php,Forms,我得到了一个POST表单,它确实会将数据发送到同一个文件中,如果使用浏览器中的“后退”按钮,他可以轻松地重新发送数据,数据仍然会被读取 有什么方法可以避免这种行为吗?如果用户想这样做,你不能100%地防止这种情况发生,但是为了避免意外发生这种情况,请仔细查看。发送表单时,将一个随机数推入$\u会话['stopdupe']值,并放入一个隐藏字段 收到表格进行处理时: 检查$\u会话['stopdupe']是否存在,并与隐藏字段的值匹配。(如果不是,请忽略此帖子) 取消设置$\u会话['stopdu

我得到了一个
POST
表单,它确实会将数据发送到同一个文件中,如果使用浏览器中的“后退”按钮,他可以轻松地重新发送数据,数据仍然会被读取


有什么方法可以避免这种行为吗?

如果用户想这样做,你不能100%地防止这种情况发生,但是为了避免意外发生这种情况,请仔细查看。

发送表单时,将一个随机数推入
$\u会话['stopdupe']
值,并放入一个隐藏字段

收到表格进行处理时:

  • 检查
    $\u会话['stopdupe']
    是否存在,并与隐藏字段的值匹配。(如果不是,请忽略此帖子)
  • 取消设置
    $\u会话['stopdupe']
  • 按正常方式处理表单
  • 这样,如果用户按下提交按钮两次,第二个请求将不会被处理


    另一个有用的技巧是使用表单上的
    onSubmit
    javascript事件来禁用按钮,这样用户就不容易多次提交按钮。

    Levi发送的链接将为您解答。但如果你想要另一种选择,我会这样做

    用户发布到类,如您的。相同的文件。在课程开始时,我做后期处理。对于这个例子,我将使它非常简单

    <?php
    session_start();
    
    //set form vars ahead of time so you can pre-populate the value attr on post
    $form = array(
        'name' => '',
        'email' => ''
    );
    
    if(!empty($_POST))
    {
        //do some kind of validation...
        $errors = array();
        if(trim($_POST['name']) == '')
            $errors[] = 'Please enter your name';
    
        if(empty($errors))
        {
            $_SESSION['message'] = 'Thank you for participating';
            header('location: /form.php'); // same file
            exit;
        }
        else
        {
            // set the form vars to the post vars so you don't lose the user's input
            $form['name'] = $_POST['name'];
            $form['email'] = $_POST['email'];
    
            $message = '<span style="color:red">';
            foreach($errors AS $error)
            {
                $message .= $error."<br />";
            }
            $message .= '</span>';
            $_SESSION['message'] = $message;
        }
    }
    
    if(isset($_SESSION['message']))
    {
        echo $_SESSION['message'];
        unset($_SESSION['message']);
    }
    ?>
    <form id="some_form" action="" method="post">
        <fieldset>
            <label for="name">Name</label> <input type="text" name="name" value="<?php echo $form['name']; ?>" />
            <br /><br />
            <label for="email">Email</label> <input type="text" name="email" value="<?php echo $form['email']; ?>" />
            <br /><br />
            <input type="submit" name="submit" value="Submit" />
        </fieldset>
    </form>
    
    
    
    这个名字对我有用。我使用smarty,但也可以不用smarty。这只是一个想法。根据需要修改它

    HTML表单:

    <form action="submit_file.php" method="POST">
    <input type="hidden" name="submit_edit" value="1">
    <input type="text" name="data"/>
    </form>
    

    在第一页中,使用一个会话变量并将值赋给1。例如:

    <form name="frm1" method="post">
        <?php $_SESSION['resend_chk']=1; ?>
        <input type="text" name="a" />
        <input type="submit" name="submit">
    </form>
    

    它将在数据库中插入一次或事务将发生一次,会话变量的值将更改,下次我们尝试重新发送数据时,它将不会执行任何事务,因为会话变量的值已更改。

    有两种通用方法

    后置获取 首先是
    post redirect get
    模式,用户在
    signup.php
    上填写表单,该模式将
    post
    发送到
    submit.php
    ,成功完成后将
    redirect
    发送回
    谢谢.php
    。浏览器会看到重定向响应,并发出一个GET for
    Thank.php
    。这是因为在没有重定向的情况下,点击refresh将重新加载
    submit.php
    ,导致重新发布表单数据警告,并双重发出
    post
    请求。重定向解决了这个问题

    signup.php
    -----------
    ...
    <input type="text" name="email">
    ...
    
    submit.php
    ----------
    ...
    if ($_POST) {
      // process data
      header('Location: thanks.php');
    }
    ...
    
    thanks.php
    ----------
    ...
    Thanks
    ...
    

    服务器需要跟踪所有的nonce密钥问题(在数据库或其他地方),当它收到表单时,它将处理表单并从数据库中删除nonce密钥。如果用户再次提交表单,nonce键将不存在,服务器可以通过忽略或发出警告来处理此问题。

    这不是完全重复的,但答案是相同的:@LeviMorrison Yea,我以前搜索过一点,找到了相同的,但我真的不知道该怎么做才能得到公认的答案。@LeviMorrison你能告诉我你为什么贬低我的问题吗?@Cyclone可能是因为这个问题以前在这里得到了回答(我猜是他的意见,而不是我的意见)。可能与它所关注的人重复:如果你否决我的答案,请告诉我为什么这样我才能提高。好吧,不是同一个人否决了这个问题,因为是我。@LeviMorrison你不应该贬低我的问题!我敢打赌,被否决的人(不是我)是因为强烈使用了“不能100%阻止这件事”,也许你在读这篇文章时会说没有办法,而不是真的读这篇文章。请注意,这可能会让同一个网站的两个标签同时打开而无法工作。这是真的,@middus。更完整的解决方案是将一个随机值推送到
    $\u会话['stopdupe']
    数组和隐藏字段中,然后在post上检查并从数组中删除该值。这听起来非常聪明!难怪你称自己为MrTrick;)。很好:)谢谢,但它省钱吗?:it’我对安全不太了解。你是说安全吗?让我们这样说吧——浏览器窗口是一个单独的进程。一页一页。$\u POST操作将使用POST数据重新加载页面-这就是我们的脚本所在。一旦它到达该标题行,它就会终止该进程并加载新页面,该页面不会传递任何post数据。你应该非常安全。哦,还有一件事:如果我想检查$\u帖子中的错误,然后显示它们呢?我不能这样做,因为标头会破坏整个输出。只有在验证是干净的情况下,才能转到标头路径。如果没有,则按预期加载页面,除了用post变量预填充表单,这样用户就不会生气,也不会显示错误,不管您选择什么。。。我将修改答案以反映这一点。。。
    require_once("globals.php");
    
    if(isset($_POST['submit_edit']) && $_POST['submit_edit'] == '1')){
    //record data
    }
    
    $oSmarty->dysplay(some.tpl);//in some.tpl is included head.tpl
    
    <form name="frm1" method="post">
        <?php $_SESSION['resend_chk']=1; ?>
        <input type="text" name="a" />
        <input type="submit" name="submit">
    </form>
    
    if(isset($_REQUEST['submit'])
    {
        if($_SESSION['resend_chk']==1)
        {
            insert to db OR and any transaction
            $_SESSION['resend_chk']=0;
        }
    }
    
    signup.php
    -----------
    ...
    <input type="text" name="email">
    ...
    
    submit.php
    ----------
    ...
    if ($_POST) {
      // process data
      header('Location: thanks.php');
    }
    ...
    
    thanks.php
    ----------
    ...
    Thanks
    ...
    
    <input type="nonce" value="<?= uniqid(); ?>">