如何在SESSION和html表单中处理多个安全性令牌

时间:2013-04-28 09:04:22

标签: php security

出于安全考虑,我想在评论表单中使用安全令牌作为隐藏输入字段。我知道如果我的网页中只有一个表单,我可以做一些像这样的事情

$token = sha1(uniqid(rand(), TRUE));
$_SESSION['token'] = $token;

我可以在我的表单中使用此令牌

<form action="comment.php" method="post">
<input type="hidden" name="token" value="<?php echo $token; ?>" />
<input type="text" name="comment_body" value="" />
</form>

在接收端,我可以这样做

if ($_POST['token'] == $_SESSION['token']){ 

   /* Valid Token */

}

但是我在一个页面上有大约10个表单所以我如何生成多个令牌以及如何在接收端处理它们。什么如果用户打开多个页面?

2 个答案:

答案 0 :(得分:0)

你可以使用microtime和mt_rand的组合,我在处理这种情况时基本上会使用它

$tokenLen = 64;

$randomData = mt_rand() . mt_rand() . mt_rand() . mt_rand() . microtime(true) . uniqid(mt_rand(), true);

$token =  substr(hash('sha512', $randomData), 0, $tokenLen);

答案 1 :(得分:0)

为防止CSRF,a single session-dependent token does already suffice

但是,如果要为每个表单使用不同的标记,则可以将标记与表单特征相关联,例如,操作URL和方法,例如:

// issue token
$form = array('method'=>'POST', 'uri'=>'/comment.php');
if (!isset($_SESSION['CSRF_TOKENS']["{$form['method']}:{$form['uri']}"])) {
    $_SESSION['CSRF_TOKENS']["{$form['method']}:{$form['uri']}"] = generate_csrf_token();
}
echo '<form method="'.$form['method'].'" action="'.$form['uri'].'">';
echo '<input type="hidden" name="CSRF_TOKEN" value="'.$_SESSION['CSRF_TOKENS']["{$form['method']}:{$form['uri']}"].'">';


// check token
$form = array('method'=>$_SERVER['REQUEST_METHOD'], 'uri'=>$_SERVER['REQUEST_URI']);
if (isset(${'_'.$form['method']}['CSRF_TOKEN'], $_SESSION['CSRF_TOKENS']["{$form['method']}:{$form['uri']}"]) && ${'_'.$form['method']}['CSRF_TOKEN'] === $_SESSION['CSRF_TOKENS']["{$form['method']}:{$form['uri']}"]) {
    // token valid
} else {
    // token missing or invalid
}

另一种可能的解决方案是使用signed CSRF tokens。除了用户ID之外,您可以添加给定示例以及进一步限制令牌有效性的其他信息。