【问题标题】:Unique token with form submit doesn't seem to work带有表单提交的唯一令牌似乎不起作用
【发布时间】:2012-02-23 11:59:34
【问题描述】:

这就是我想做的:

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

<?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>

【问题讨论】:

  • 你在每次页面加载时创建一个新的$_SESSION['token'](“time()”的值不断变化),所以条件总是满足的。
  • 表单提交后重定向到同一页面,防止表单重新提交
  • @Rémi 我将令牌更改为... $_SESSION['token'] = md5(uniqid());...但我仍然有同样的问题,它说“不要发送两次“我第一次提交。你能展示一些代码示例吗?
  • 这不是重点。您在每个请求中重新生成一个新的会话令牌(无论是第一个 GET 还是后面的 POST),因此这些条件“if (isset($_SESSION['token']))”和“if ($_POST[ 'token'] != $_SESSION['token'])" 总是正确的。仅在令牌不存在时才生成令牌,并且您应该开始获得更好的结果。同样正如前面的评论所建议的,为了防止重新提交,使用redirect after post 模式更容易。
  • 好吧,你受够了,不知道我是否知道如何创建一个不存在的令牌,但我会尝试重定向后发布模式!

标签: php forms token


【解决方案1】:

这里的概念是有缺陷的。

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

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

我建议将提交保存在数据库中。这保证了同一个会话(或同一个用户)只能保存一条记录。

【讨论】:

  • 非常有效的观点!如果它真的只是为了确保它不会被提交两次,那么令牌不会有太大帮助。仍然建议使用表单令牌来保护自己免受 CSRF 的影响。
【解决方案2】:

Thank you for submitting 永远不会显示,因为if( isset($_SESSION['token']) ) 的条件始终满足,因为您生成令牌并将会话变量设置在此 if 子句的正上方...这也是您总是会看到“don”的原因第一次提交后发送两次。 加载表单时生成令牌,将其保存在会话中,将其放入表单中。 提交表单后,从顶部再次启动脚本: 您的令牌现在位于 post 变量中。但是您重新创建了会话令牌。然后你比较帖子和会话。当然它们不匹配,因为你刚刚生成了一个 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>

【讨论】:

    猜你喜欢
    • 2016-07-19
    • 2016-12-08
    • 2013-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-08
    • 2018-07-30
    • 1970-01-01
    相关资源
    最近更新 更多