PHP提交表单时如何防止多次插入?

发布于 2024-08-19 03:14:35 字数 137 浏览 6 评论 0原文

有时,用户可能会按两次 Enter,帖子就会插入两次。

除了检查是否已经存在具有相同 titlecontent 的帖子之外,是否有解决方案可以防止这种情况发生?

Sometimes the user may press Enter twice, and the post is inserted twice.

Is there a solution to prevent this other than check if there is already a post with the same title and content?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

弃爱 2024-08-26 03:14:35

此问题有多种解决方案:

  1. 在发布表单时使用 Javascript 禁用表单的提交按钮。这样做的缺点是,这绝对不是万无一失的方法。无需实际单击按钮即可提交表单非常容易,这对于禁用 JavaScript 的用户也不起作用。 我绝对不会推荐这种方法。

    示例:

    <脚本语言=“javascript”>
    
    
    <表单操作=“foo.php”方法=“post”>
        <输入类型=“文本”名称=“栏”/>>
        
    
    
  2. 使用PHP 会话 将会话变量(例如 $_SESSION['posttimer'])设置为发布的当前时间戳。在 PHP 中实际处理表单之前,请检查 $_SESSION['posttimer'] 变量是否存在,并检查是否存在一定的时间戳差异(即:2 秒)。这样,您就可以轻松过滤掉重复提交。

    示例:

    // form.html
    <表单操作=“foo.php”方法=“post”>
        <输入类型=“文本”名称=“栏”/>
        <输入类型=“提交”值=“保存”>
    
    
    // foo.php
    if (isset($_POST) && !empty($_POST)) 
    {
        if (isset($_SESSION['posttimer']))
        {
            if ( (time() - $_SESSION['posttimer']) <= 2)
            {
                // 自上次发布以来不到 2 秒
            }
            别的
            {
                // 自上次发布以来已超过 2 秒
            }
        }
        $_SESSION['posttimer'] = time();
    }
    
  3. 在每个 POST 上包含唯一的令牌。在这种情况下,您还可以将会话变量设置为要包含的令牌,然后呈现该令牌在形式中。提交表单后,您将重新生成令牌。当提交的令牌与您会话中的令牌不匹配时,表单已重新提交,并且应被声明为无效。

    示例:

    // form.php
    
    <表单操作=“foo.php”方法=“post”>
        >
        <输入类型=“文本”名称=“栏”/>>
        <输入类型=“提交”值=“保存”/>
    
    
    // foo.php
    if (isset($_SESSION['令牌']))
    {
        if (isset($_POST['令牌']))
        {
            if ($_POST['令牌'] != $_SESSION['令牌'])
            {
                // 双重提交
            }
        }
    }
    

There are several solutions to this problem:

  1. Use Javascript to disable the form's submit button when it is posted. Downside to this is that this is ABSOLUTELY not a foolproof way. It's very easy to submit forms without actually clicking the button, and this would also not work for users with JavaScript disabled. I would definitely not recommend this method.

    Example:

    <script language="javascript">
    <!--
        function disableSubmitButton() {
            // you may fill in the blanks :)
        }
    -->
    </script>
    <form action="foo.php" method="post">
        <input type="text" name="bar" />
        <input type="submit" value="Save" onclick="disableSubmitButton();">
    </form>
    
  2. Use PHP sessions to set a session variable (for example $_SESSION['posttimer']) to the current timestamp on post. Before actually processing the form in PHP, check if the $_SESSION['posttimer'] variable exists and check for a certain timestamp difference (IE: 2 seconds). This way, you can easily filter out double submits.

    Example:

    // form.html
    <form action="foo.php" method="post">
        <input type="text" name="bar" />
        <input type="submit" value="Save">
    </form>
    
    // foo.php
    if (isset($_POST) && !empty($_POST)) 
    {
        if (isset($_SESSION['posttimer']))
        {
            if ( (time() - $_SESSION['posttimer']) <= 2)
            {
                // less then 2 seconds since last post
            }
            else
            {
                // more than 2 seconds since last post
            }
        }
        $_SESSION['posttimer'] = time();
    }
    
  3. Include a unique token on each POST. In this case, you would also set a session variable to the token you want to include and then render the token in the form. Once the form is submitted, you re-generate the token. When the submitted token does not match the token in your session, the form has been re-submitted and should be declared invalid.

    Example:

    // form.php
    <?php
        // obviously this can be anything you want, as long as it is unique
        $_SESSION['token'] = md5(session_id() . time());
    ?>
    <form action="foo.php" method="post">
        <input type="hidden" name="token" value="<?php echo $_SESSION['token'] ?>" />
        <input type="text" name="bar" />
        <input type="submit" value="Save" />
    </form>
    
    // foo.php
    if (isset($_SESSION['token']))
    {
        if (isset($_POST['token']))
        {
            if ($_POST['token'] != $_SESSION['token'])
            {
                // double submit
            }
        }
    }
    
献世佛 2024-08-26 03:14:35

在帖子中使用唯一的令牌,以便每个帖子/回发仅处理一次。

禁用提交按钮并不是一个很好的解决方案,因为人们可能会关闭 JavaScript,或者做其他奇怪的事情。客户端验证是一个好的开始,但也应该始终与服务器端处理一起支持。

Use a unique token with the post, so that each post/postback is only handled once.

Disabling the submit button is not a very good solution since people could have javascript turned off, or doing other weird things. Client side validation is a good start, but should always be backed up with server side handling as well.

丢了幸福的猪 2024-08-26 03:14:35

生成一个唯一的一次性使用密钥以与表单一起提交。

依赖 Javascript 是一个坏主意,因为它可能已被用户在客户端中禁用。使用密钥方案,当服务器接收到提交时,可以锁定该密钥的提交。您可以根据自己的喜好回复重复提交的内容。

为了使这种方法发挥作用,密钥必须是唯一的并且很难预测。否则,某些表单可能会因按键冲突而被锁定。因此,您不必跟踪每个表单提交的密钥并避免冲突,密钥应该随着该用户的会话而过期。另一件需要注意的事情是,如果恶意用户能够预测密钥,您的代码可能容易受到某种劫持或 DOS 攻击。

Generate a unique, one-time use key to submit with the form.

Relying on Javascript is a bad idea because it may have been disabled in the client by the user. With the key scheme, when the submit is received by the server, submission for that key can be locked. You can respond to duplicate submits however you like.

For this approach to work, keys must be unique and very difficult to predict. Otherwise some forms could be locked due to key collisions. So you don't have to track keys for every form submission and avoid collisions, keys should expire with that user's session. The other thing to watch out for is if malicious users are able to predict the key, your code may be vulnerable to some kind of hijacking or DOS exploit.

ι不睡觉的鱼゛ 2024-08-26 03:14:35

提交表单后,使用 Javascript 禁用提交按钮 (onsubmit)。

请注意,如果用户禁用了 Javascript,他们仍然可以提交两次。这种情况是否经常发生足以证明检查代码是合理的(正如您在问题中所建议的那样)取决于您。

Disable the submit button using Javascript once the form gets submitted (onsubmit).

Note that if the user has disabled Javascript, they can still submit twice. Whether or not this happens often enough to justify also checking in your code (as you suggested in your question) is up to you.

别靠近我心 2024-08-26 03:14:35

或者,使用一次性表单键。

Alternatively, use one-time form keys.

他不在意 2024-08-26 03:14:35

我使用这个:

$form_token = $_SESSION['form_token'] = md5(uniqid());

将 $form_token 与表单一起发送,然后...

我检查 form_token:

if($_SESSION['form_token'] != $_POST['form_token']) {
   echo 'Error';
}

I use this:

$form_token = $_SESSION['form_token'] = md5(uniqid());

send $form_token with the form, then...

I check the form_token:

if($_SESSION['form_token'] != $_POST['form_token']) {
   echo 'Error';
}
终遇你 2024-08-26 03:14:35

用户使用 JavaScript 提交表单后禁用提交按钮。例如,这就是 StackOverflow 在您回答问题时使用的内容。

例如

<input type="submit" onclick="this.disabled=true" />

disable the submit button once the user has submitted the form, using JavaScript. That is what, for example, StackOverflow uses when you answer a question.

For example

<input type="submit" onclick="this.disabled=true" />
深空失忆 2024-08-26 03:14:35

按提交两次很少会导致多次插入,但如果您想要一个非常简单的解决方案,请

onsubmit="document.getElementById('submit').disabled = true"

在表单标记中使用,前提是您提供提交按钮 id="submit"

Pressing submit twice quite rarely results in multiple inserts, but if you want a dead-simple sollution, use

onsubmit="document.getElementById('submit').disabled = true"

in the form tag, provided you give your submit button id="submit"

怼怹恏 2024-08-26 03:14:35

单击按钮后立即使用 JavaScript 禁用该按钮。

onclick="this.disabled=true;forms[0].submit();"

Use a JavaScript to disable the button as soon as it is clicked.

onclick="this.disabled=true;forms[0].submit();"
狼性发作 2024-08-26 03:14:35

创建确认页面的另一种方法,用户最终可以在其中按下提交按钮。它可能会减少这种可能性。

Another way to create a confirmation page where user can finally press the submit button. It might reduce the possibilities of this kind.

岁月苍老的讽刺 2024-08-26 03:14:35

我正在对 action.php 执行以下操作

if($_SESSION && isset($_SESSION['already_submitted'])) {

  # If already submitted just redirect to thank you page

} else {

    # If first submit then assign session value and process the form
    $_SESSION['already_submitted'] = true;

    # Process form

}

注意:始终使用 session_start() 在标头中启动会话;

I'm doing the following on the action.php

if($_SESSION && isset($_SESSION['already_submitted'])) {

  # If already submitted just redirect to thank you page

} else {

    # If first submit then assign session value and process the form
    $_SESSION['already_submitted'] = true;

    # Process form

}

Note: Always initiate your sessions in the header using session_start();

清风挽心 2024-08-26 03:14:35

Aron Rotteveel 的在每个帖子上包含一个唯一的令牌对我有用。但是,当用户刷新页面(F5)时,我的表单仍然会提交。我设法通过添加重置来解决这个问题:

            // reset session token
            $_SESSION['token'] = md5( $_POST['token'] . time() );

我的最终脚本如下:

if (isset($_SESSION['token'])) {
    if (isset($_POST['token'])) {
        if ($_POST['token'] != $_SESSION['token']) {
            echo '<h3>Oops! You already submitted this request.</h3>';
        } else {
            // process form
            // reset session token
            $_SESSION['token'] = md5( $_POST['token'] . time() );
        }
    } else {
        echo 'post token not set';
        $_SESSION['token'] = md5( $somevariable . time() );
    }
}

哦!不要忘记在 之前添加 session_start();

我是 PHP 新手,如果您发现违规行为,请纠正我。

Aron Rotteveel's Include a unique token on each POST worked for me. However, my form still submits when a user refreshes the page (F5). I managed to solve this by adding a reset:

            // reset session token
            $_SESSION['token'] = md5( $_POST['token'] . time() );

my final scripts goes like:

if (isset($_SESSION['token'])) {
    if (isset($_POST['token'])) {
        if ($_POST['token'] != $_SESSION['token']) {
            echo '<h3>Oops! You already submitted this request.</h3>';
        } else {
            // process form
            // reset session token
            $_SESSION['token'] = md5( $_POST['token'] . time() );
        }
    } else {
        echo 'post token not set';
        $_SESSION['token'] = md5( $somevariable . time() );
    }
}

oh! don't forget to add session_start(); before <!DOCTYPE>

I am a PHP newbie so please correct me if you find irregularities.

梦晓ヶ微光ヅ倾城 2024-08-26 03:14:35

使用 JavaScript 阻止其发送

Use JavaScript to stop it from sending

油饼 2024-08-26 03:14:35
$(document).ready(function() {
  $('#postHideBtn').show();
  $('#postHideBtn').click(function() {
    $('#postHideBtn').hide();
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<form action="foo.php" method="post">
  <input type="text" name="bar" />
  <input type="submit" value="Save" id="postHideBtn" />
</form>

$(document).ready(function() {
  $('#postHideBtn').show();
  $('#postHideBtn').click(function() {
    $('#postHideBtn').hide();
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<form action="foo.php" method="post">
  <input type="text" name="bar" />
  <input type="submit" value="Save" id="postHideBtn" />
</form>

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文