0

出于安全目的,我想将安全令牌用作评论表单中的隐藏输入字段。我知道如果我的网页中只有一个表格,我可以做类似的事情

$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 个表单,所以我如何生成多个令牌以及如何在接收端处理它们。如果用户打开多个页面怎么办?

4

2 回答 2

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);
于 2013-04-28T09:07:37.873 回答
0

为了防止 CSRF,一个依赖于会话的令牌已经足够了

但是,如果您想为每个表单使用不同的标记,您可以将标记与表单特征相关联,例如操作 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
}

另一种可能的解决方案是使用签名的 CSRF 令牌。您可以在给定示例中添加除用户 ID 之外的尽可能多的附加信息,以进一步限制令牌的有效性。

于 2013-04-28T10:31:21.250 回答