Php 如何从阵列中删除未使用的安全令牌

Php 如何从阵列中删除未使用的安全令牌,php,csrf-protection,Php,Csrf Protection,我遇到了一个问题,我找不到任何解决办法。问题是,当用户打开一个页面时,会生成这样的安全令牌,并将其添加到会话数组中 $token = generate_csrf_token(); $_SESSION['tokens'][] = $token; 我在表单提交中使用这个$token作为CSRF安全性的隐藏输入。 现在,问题是,如果用户发布任何评论,我可以在像这样发布评论之后从数组中删除$token $token = $_POST['token']; // comment posting proc

我遇到了一个问题,我找不到任何解决办法。问题是,当用户打开一个页面时,会生成这样的安全令牌,并将其添加到会话数组中

$token = generate_csrf_token();
$_SESSION['tokens'][] = $token;
我在表单提交中使用这个$token作为CSRF安全性的隐藏输入。 现在,问题是,如果用户发布任何评论,我可以在像这样发布评论之后从数组中删除$token

$token = $_POST['token'];

// comment posting process

$key = array_search($token, $_SESSION['tokens']);
unset($_SESSION['tokens'][$key]);

但如果用户没有发表任何评论并退出页面,我如何才能从
$\u会话['tokens'][
数组中删除该$token。如果我不删除,这可能会导致数组中有太多未使用的$token。

在正常情况下,一旦用户退出页面,其引用会话的cookie将被清除。(当他关闭浏览器时)。下次他打开浏览器并访问您的页面时,他将开始新的会话

现在,因为他丢失了对您会话的引用,并且没有其他人在使用它,会话文件将不再被访问,并且一旦它在一定时间内未被访问,垃圾收集器将清除它

因此,当用户离开页面时,您不必担心“清除安全令牌”。这是自动处理的。当然,除非你自己搞砸了会话管理。有关可以更改的选项,请参见信息

现在,如果您的目标是在用户仍在使用同一会话的页面上时清除令牌,那么有几个选项

第一种是每个会话使用一个安全令牌。如果用户关闭页面(读取:在您的站点上加载另一个页面),则他将在
$\u会话['token']
(无数组)中发布一个新令牌,并清除旧令牌。这确实要求您在更改令牌之前,在
POST
之后检查令牌

另一种选择是只保留最后5个左右的代币。然后,您可以保持它干净,而无需更改令牌的检查。你可以用它来做

<?
$tokens[] = 'new token';
if (count($tokens)>5) {
  array_shift($tokens); //first is removed, so the last 5 remain
}
?>


我能想到的最后一种方法是在令牌中添加一个时间,在页面请求中,循环遍历所有令牌并检查时间。如果过去的时间超过xx分钟,请将其删除。

与任何异步客户机-服务器状态一样,答案是超时。你不能保证代币会被使用,即使它最终被使用,你也无法知道何时被使用。对于未使用的令牌也没有明确的反馈机制;未使用的代币永远不会被使用

因此,将时间戳与每个令牌相关联。定期检查所有存储的令牌,并删除您认为已过期的令牌。选择合理的到期时间。例如:

// 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]);
        }
    }
}
//大约每加载100页运行一次垃圾收集
如果(mt_rand(01100)==0){
foreach($\会话['tokens']作为$i=>$token){
如果($token['timestamp']

由于会话最终都会通过相同的机制自行过期,因此您可以简单地将这一问题留给会话过期时解决。

何时终止会话?