我遇到了问题,我无法找到任何解决方案。问题是当用户打开页面时,正在生成这样的安全令牌并添加到SESSION数组
$token = generate_csrf_token();
$_SESSION['tokens'][] = $token;
我在表单提交中使用此$令牌作为CSRF Security的隐藏输入。 现在,问题是,如果用户发布任何评论,我可以在评论发布后从数组中删除$令牌
$token = $_POST['token'];
// comment posting process
$key = array_search($token, $_SESSION['tokens']);
unset($_SESSION['tokens'][$key]);
但是如果用户不发布任何评论并退出页面,如何,我可以从$_SESSION['tokens'][]
数组中删除该$令牌。如果我不删除,这可能会导致数组中有这么多未使用的$令牌。
答案 0 :(得分:1)
在正常情况下,一旦用户退出页面,他的cookie将被清除。 (当他关闭浏览器时)。下次他打开浏览器并访问您的页面时,他将开始一个新的会话。
现在因为他丢失了对你的会话的引用而没有其他人正在使用它,会话文件将不再被访问,一旦它没有访问一段时间,垃圾收集器将清除它。
因此,当用户离开页面时,您无需担心“清除安全令牌”。这是自动处理的。除非您自己搞过会话管理。有关您可以更改的选项,请参阅session settings信息。
现在,如果您的目标是在用户使用同一会话仍然在页面上时清除令牌,则有几个选项。
第一种方法是每个会话使用一个安全令牌。如果用户关闭页面(读取:在您的站点上加载另一个页面),那么他将在$_SESSION['token']
(没有数组)中发出新令牌,并清除旧令牌。这确实需要您在更改之前检查令牌POST
。
另一个选择是只保留最后5个左右的标记。然后你可以保持清洁,而无需改变令牌的检查。您可以使用array_shift来执行此操作
<?
$tokens[] = 'new token';
if (count($tokens)>5) {
array_shift($tokens); //first is removed, so the last 5 remain
}
?>
我能想到的最后一种方法是在令牌和页面请求上添加时间,循环所有令牌并检查时间。如果时间超过过去的xx分钟,请将其删除。
答案 1 :(得分:1)
与任何异步客户端 - 服务器状态一样,答案是超时。您无法保证将永久使用令牌,即使它最终被使用,您也无法知道何时。对于未使用的令牌,也没有明确的反馈机制;未使用的令牌根本就没用过。
因此,将时间戳与每个令牌相关联。您定期检查所有存储的令牌并删除您认为已过期的令牌。选择合理的到期时间表。 E.g:
// run garbage collection roughly every 100 page loads
if (mt_rand(0, 100) == 0) {
foreach ($_SESSION['tokens'] as $i => $token) {
if ($token['timestamp'] < time() - 3600) {
unset($_SESSION['tokens'][$i]);
}
}
}
由于会话最终会通过相同的机制自行过期,也许你可以简单地将其留给会话到期。