表单提交的唯一令牌不';似乎不起作用


Unique token with form submit doesn't seem to work

这就是我想要做的:

防止用户使用唯一令牌两次提交表单。我想我这里有正确的代码,但它仍然不起作用。第一次提交表单时,输出为"不要发送两次"。我做错了什么?

<?php session_start(); ?>
<html>
<body>
<?php
 $_SESSION['token'] = md5(session_id() . time());
?>
<?php
if (isset($_SESSION['token']))
{
if (isset($_POST['token']))
{
    if ($_POST['token'] != $_SESSION['token'])
    {
       echo "Don't send twice!"; 
    }
}
}
else {
echo "Thank you for submitting";
} 
?>
<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
<input type="hidden" name="token" value="<?php echo $_SESSION['token'] ?>" />
<input type="text" name="bar" />
<input type="submit" value="Save" />
</form>

这里的概念有缺陷。

  1. 浏览器不允许用户使用POST两次提交表单。他们向用户显示一个警告,告知提交两次表格的危险。

  2. 如果用户两次加载表单,则此脚本无法避免两次提交,因为两个表单上的令牌不同。

我建议将提交的内容保存在数据库中。这样可以确保同一会话(或同一用户)只能保存一条记录。

Thank you for submitting永远不会显示,因为if( isset($_SESSION['token']) )的条件总是满足的,因为您生成了令牌并将会话变量设置在if子句的正上方。。。这也是为什么你在第一次提交后总是会看到"不要发送两次"。加载表单时,您生成一个令牌,将其保存在会话中,并将其放入表单中。提交表单后,您将从顶部重新启动脚本:您的代币现在位于后变量中。但是您重新创建了会话令牌。然后比较post和session。它们当然不匹配,因为您刚刚生成了一个NEW令牌,所以它们当然不相等。

我为您的代码推荐这种结构:

<html>
<body>
<?php 
session_start(); 
//HAS THE FORM BEEN SUBMITTED?
if(isset($_POST))
{
    //THE FORM HAS BEEN SUBMITTED
    //VALIDATE THE TOKEN
    if($_POST['token'] == $_SESSION['token'])
    {
        //THE TOKEN WAS VALID, CONTINUE WITH PROCEDURES
    }
    else
    {
        echo 'Invalid token, please try again!';
    }
}
else
{
    //FORM NOT SUBMITTED YET
    $token = $_SESSION['token'] = md5( session_id() . time(). rand() ); 
    //i recommend adding rand() otherwise there is always a 1 second window in which the token could be doubled up...
    echo '<form action="'. $_SERVER['PHP_SELF'] .'" method="post">';
    echo '<input type="hidden" name="token" value="'. $token .'" />';
    echo '<input type="text" name="bar" />';
    echo '<input type="submit" value="Save" />';
    echo '</form>';
}
?>
</body>
</html>