Token方式防御CSRF攻击,当打开多个页面,前面的页面Token失效怎么办?

//test.php
<?php
session_start();
$token = base64_encode(openssl_random_pseudo_bytes(32));
$_SESSION['token'] = $token;
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>csrf demo</title>
</head>
<body>
    <form action="token.php" method="POST">
        <input type="hidden" name="token" value="<?= $token ?>">
        <input type="submit" value="Submit">
    </form>
</body>
</html>
// token.php
<?php
session_start();
if ($_SERVER['REQUEST_METHOD'] == 'POST' and (! isset($_POST['token']) || $_POST['token'] == $_SESSION['token'])) {
    echo 'request success';
} else {
    echo 'csrf forbidden';
}

Token方式防御csrf攻击,当打开多个页面,前面的页面表单失效怎么办?有没有什么简单方法能让之前的Token有效,并能有效防御csrf攻击?

阅读 3.6k
1 个回答

存多个 token 呗。

比如以 SessionId + token 的方式给 Redis 添加一个 Key,去验证这个 Key 是否存在,而不是简单的判断 $_POST['token'] == $_SESSION['token']。这样甚至还可以利用 Redis 可以给 Key 设置过期时间的方式,来实现给 token 也设置过期时间的效果。

不想用 Redis 也行,那 $_SESSION['token'] 里就需要存多个,可以用逗号之类的分隔开,$_SESSION['token'] .= (', '. $token),然后验证的时候反向判断是否包含就可以了。

思路就是这样,实现方式有很多,你可以自己再琢磨琢磨。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题