//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攻击?
存多个 token 呗。
比如以 SessionId + token 的方式给 Redis 添加一个 Key,去验证这个 Key 是否存在,而不是简单的判断
$_POST['token'] == $_SESSION['token']
。这样甚至还可以利用 Redis 可以给 Key 设置过期时间的方式,来实现给 token 也设置过期时间的效果。不想用 Redis 也行,那
$_SESSION['token']
里就需要存多个,可以用逗号之类的分隔开,$_SESSION['token'] .= (', '. $token
),然后验证的时候反向判断是否包含就可以了。思路就是这样,实现方式有很多,你可以自己再琢磨琢磨。