如何有效地处理 PHP 个会话?

How to handle PHP sessions efficiently?

这是我的 init.php 在整个网站上加载的样子:

$suid = 0;
session_set_cookie_params(60, '/', '.' . $_SERVER['HTTP_HOST'], true);
session_save_path(getcwd() . '/a/');
if (!isset($_SESSION['id'])) {
    session_start(['cookie_lifetime' => 60]);
    $_SESSION['id'] = session_id();
    $_SESSION['start'] = date('d_m_Y_H_i');
    $_SESSION['ip'] = $_SERVER['REMOTE_ADDR'];
} elseif (isset($_SESSION['uid'])) {
    $suid = $_SESSION['uid'];
}

我目前正在测试 PHP 个会话,所以我只将 60 秒作为生命周期。

我想知道为什么要创建会话,因为还没有人知道域,所以我添加了 ip。我查了一下,发现了这个:

原来是 Google 爬虫机器人。由于那里有更多的搜索引擎和机器人,我不想将这些爬行保存在我的会话文件中并用它填充我的网站空间。

所以我的问题是:

1) 即使测试生命周期值(60 秒)结束,会话文件仍保留在自定义目录中。我读到这是因为我设置了一个自定义目录。这是真的吗?

2) 删除所有 non-used/expired 会话文件的有效方法是什么?我应该添加带有时间戳的 $_SESSION['last_activity'] 并让 cronjob 查看我的自定义目录,获取会话文件数据并计算过期会话以将其删除吗?

3) 我应该避免那些只在 $_SERVER['HTTP_HOST'] 中寻找字符串 "bot" 的机器人爬虫保存那些不需要的会话,还是有更好的方法来识别 "non-human visitors"/爬虫?

我也感谢任何 improvements/suggestions 对我顶部代码的支持。我之前只是造成了一些 Internal Server Error,因为据我从 php-fpm-slow-logs 可以看出,session_start() 经常被调用。

  1. cleanup php session files

  2. 这个 cronjob 已经存在(见 1.)- 由于内存使用和 TTL,最有效的方法是将会话数据存储在 memcached 而不是普通文件中。

  3. 你应该避免将字符串与用户代理或主机进行比较,因为它不可靠,HTTP_HOST 是你的本地主机名,而不是远程主机名,这是你不应该这样做的最重要原因对 google 机器人没有任何不同:您伪造网站的行为,这对您的 Google 排名非常不利。欢迎 google 像网站的任何其他访问者一样。

1) Even when the test lifetime value (60 seconds) is over, the session file remains in the custom directory. I read this is because I set a custom directory. Is this true?

不,自定义目录由 session GC 拾取,文件将被清理。它不会立即发生。

2) What would be an efficient way to delete all non-used/expired session files? Should I add $_SESSION['last_activity'] with a timestamp and let a cronjob look in my custom dir, get the session file data and calculate expired sessions to delete it?

PHP 7.1 有 session_gc(),你可以从 cronjob 调用它,它会做所有必要的事情。

在旧的 PHP 版本中,默认情况下您会依赖 probability-based GC,其中随机执行清理。
这可能不是特别有效,但它是十多年来唯一通用的解决方案,所以 ...

但是,如果您的服务器运行 Debian,它可能将 session.gc_probability 设置为 0 并使用一个 Debian-specific crontab 脚本,用于定期进行清理 - 在这种情况下,您将遇到自定义目录的问题,并且有几个选项:

  • 手动 re-enable session.gc_probability.
  • 直接在 php.ini 中配置 session.save_path,这样默认的 cron 脚本就可以使用它了。
  • 不要使用自定义目录。鉴于您目前有 getcwd().'/a/',我想说 Debian 上的默认 sessions 目录几乎肯定是一个更安全的位置,因此客观上它会更好。
  • 编写你自己的 cronjob 来做到这一点,但你必须真正知道你在做什么。 $_SESSION['last_activity'] 甚至不能用于此; file-system 本身提供的文件 access/modified 次是。

3) Should I avoid saving those unneeded sessions by those bot crawlers just looking for the string "bot" inside $_SERVER['HTTP_HOST'] or is there a better way to identify "non-human visitors"/crawlers?

您正在考虑 $_SERVER['HTTP_USER_AGENT'],但没有 - 这不是解决方案。

鲜为人知(或为方便起见基本上被忽略),但正确执行此操作的唯一方法是永远不要在登录前启动 session .

爬虫触发无用 session 文件的烦恼是一个可以忽略不计的问题;真正令人担忧的是坚定的攻击者有能力填满您的 session 存储空间,use-up 所有可能的 session ID,避免 session.use_strict_mode - none 这些攻击很容易取消,但可能导致 DoS 或 session 固定,因此也不应轻易将其视为可能性。

P.S。额外提示:不要使用 $_SERVER['HTTP_HOST'] - 这是来自 HTTP Host header 的用户输入;由于 cookie 的工作方式,在这种情况下它可能是安全的,但通常应该避免。