PHP:如何检测会话是否自动过期?

2022-08-31 00:28:49

定义会话过期时间后,是否可以在事件侦听器过期时调用事件侦听器?

如果无法实现,是否可以运行 cron 作业来检查会话是否已过期?

注意:我对服务器解决方案感兴趣。我说的是定义了会话过期时间的情况,并且会话自动结束,因为该期限已过期。


答案 1

是否可以在事件侦听器过期时调用事件侦听器?

简短的回答是否定的

关于会话,人们往往会忽略一些奇怪的事情。使用默认处理程序,会话在结束时不会过期 - 这只是数据符合自动删除条件的时间。会话所有者不会触发会话的后续删除 - 这是其他人会话的副作用。gc_maxlifetime

当被调用时(显式调用,或由代码结尾隐式调用),如果随机数生成器(由相关gc设置调整)抛出正确的数字,则PHP将去寻找超过其TTL的数据并将其删除。如果要在此时触发操作,则需要中断默认处理程序并应用自己的处理程序。这意味着您不仅必须提供一种识别和删除会话的机制,而且还必须提供一种决定您的处理程序是否应该启动以及应该删除多少个会话的方法 - 您不希望失控的进程杀死您的服务器session_write_close()

在 Ubuntu 中,它是一个 cron 作业,它执行删除过时数据文件的功能。session.gc_probability = 0

您的问题中缺少的一条非常重要的信息是删除会话的原因。

如果要防止敏感数据保留在文件系统上,那么更好的解决方案是使用存储在(仅)另一个客户端cookie中的密钥来加密数据。这样,您就可以完全消除服务器上未受保护数据的存储。(请注意,suhosin的加密会话使用从有关客户端的数据派生的密钥和存储在同一主机上的静态密钥 - 这比随机生成的密钥安全得多)。这是我之前准备的一个

如果您只想在 过期后阻止访问,则应考虑使用自定义会话处理程序,它将过时的会话视为丢失。也就是说,它不会在到期时真正注销,但任何后续请求都不能再与会话相关联。可堆叠会话处理程序示例中的安全层实现了此类控件。gc_maxlifetime

OTOH如果您想在事件侦听器中使用会话中的数据,那么情况就不同了 - 您肯定无法使用Suhosin或我的加密来加密数据。但更复杂的是,数据的(默认)格式与其他地方使用的格式不同。您需要使用 session_encode() 和 session_decode()。前者只会从 $_SESSION 数组中读取数据,因此窃听会话需要对 和 进行一些仔细的子反转。 但是会很乐意转换你扔给它的任何东西。session_id()session_start()session_decode()

在最新版本的 PHP 中,您可以指定用于序列化/反序列化的其他函数对。

在考虑要读取会话文件中的数据的会话垃圾回收器时,考虑方法的潜在影响至关重要。与此相关的是要求处理此类垃圾回收的进程在与创建会话数据的原始PHP进程相同的uid下运行(否则您将具有权限提升后门)。但是,如果会话存储基板是基于文件的,那么无论如何都需要如此。__wakeup()

有一些用PHP以外的语言编写的会话数据反序列化器的实现可以提供针对攻击的保护(尝试Google),尽管这可能有点过分,无法解决问题,并且它们可能没有得到积极的维护。如果这是一个问题,那么更合适的解决方案可能是使用 WDDX (xml) 序列化程序,并使用传统的 XML 分析器在 GC 引擎中读回数据。__wakeup()

如果您使用本机处理程序来正常读取和写入数据,但想要实现自己的垃圾回收器,那么您将需要代码来将 映射到文件路径。如果您按照我为上面的PHP类提供的链接,您将看到几个会话处理程序的纯PHP实现,包括与本机处理程序兼容的处理程序。session_id

但是,我强烈建议您在选择在删除时读回会话数据之前,用尽所有其他途径来解决任何潜在问题。


答案 2

您也可以使用此:)

<? 
session_start();

$time = 3600; // Set expire time with secends.
// Star session here 
if (isset($_SESSION['time']) && (time() - $_SESSION['time']) > $time) {
   // Your Code Here to logout
   header('location: /auth/logout');
   exit();
} else {
  $_SESSION['time'] = time();
 }

推荐