这就是我想要做的事情:
阻止用户使用唯一令牌提交表单两次。我想我在这里有正确的代码,但它仍然不起作用。第一次提交表单时输出为“不发送两次”。我究竟做错了什么?
<?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>
答案 0 :(得分:1)
Thank you for submitting
将永远不会显示,因为if( isset($_SESSION['token']) )
的条件总是得到满足,因为您生成令牌并将会话变量直接设置在此if子句之上...这也是您将永远的原因提交第一次后看“不要发两次”。
加载表单时,您生成一个令牌,将其保存在会话中,将其放在表单中。
提交表单后,从顶部再次启动脚本:
您的令牌现在位于post变量中。但您重新创建会话令牌。然后你比较帖子和会话。当然它们不匹配,因为你刚刚生成了一个新令牌,所以它们当然不相等。
我建议您使用此结构代码:
<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>
答案 1 :(得分:1)
这里的概念存在缺陷。
浏览器不允许用户使用POST两次提交表单。他们向用户显示警告,说明两次提交表单的危险。
如果用户加载表单两次,则此脚本无法避免两次提交,因为两个表单上的令牌都不同。
我建议将提交保存在数据库中。这可以确保同一会话(或同一用户)只能保存一条记录。