PHP:如何检测会话是否自动过期? [英] PHP: how to detect if a session has expired automatically?

查看:225
本文介绍了PHP:如何检测会话是否自动过期?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

定义了会话到期时间后,是否可以在事件监听器到期时调用它?

When a session expiration time is defined, is it possible to call an event listener when it expires?

如果不可能,是否可以运行cron作业以检查会话是否已过期?

If it is not possible, is it possible to run a cron job to check if a session has expired?

注意:我对服务器解决方案感兴趣.我说的是定义了会话过期时间,并且会话自动终止,因为该时间段已过期.

NOTE: I'm interested in a server solution. I'm talking about the case there is a session expiration time defined, and the session finishes automatically because that period expired.

推荐答案

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

is it possible to call an event listener when it expires?

简短的回答是

人们在会议上往往会忽略一些奇怪的地方.使用默认处理程序,会话不会在gc_maxlifetime结束时到期-这只是数据可以自动删除的时间.会话所有者没有采取任何动作来触发该会话的后续删除-这是其他人会话的副作用.

There are a few oddities people tend to ignore about sessions. With the default handler, the session does not expire when gc_maxlifetime ends - this is just the time at which the data becomes eligible for automatic deletion. There is no action by the owner of the session which triggers the subsequent removal of the session - its a side effect of someone else's session.

调用session_write_close()时(通过代码结尾显式或隐式),如果通过相关gc设置进行了调整的随机数生成器抛出了正确的数字,则PHP将继续查找超过其TTL的数据并将其删除.如果要在此时触发操作,则需要打破默认处理程序并应用自己的处理程序.这意味着您不仅需要提供一种识别和删除会话的机制,而且还需要一种方法来确定您的处理程序是否应加入以及应删除多少个会话-您不希望使用

When session_write_close() is called (either explicitly, or implicitly by the code ending), if the random number generator, tweaked by the relevant gc settings throws the right number then PHP will go looking for data past its TTL and remove it. If you want to trigger an action at this point, then you need to break the default handler and apply your own. That means you not only have to provide a mechanism for identifying and removing sessions but also a way of deciding whether your handler should kick in and how many sessions it should delete - you don't want a runaway process killing your server.

在Ubuntu中,session.gc_probability = 0是一项cron作业,具有删除过时的数据文件的功能.

In Ubuntu, session.gc_probability = 0, and it is a cron job which carries out the function of removing stale data files.

问题中缺少的非常重要信息是删除会话的原因.

A very important piece of information missing from your question is the reason for deleting the session.

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

If you want to prevent sensitive data from persisting on the filesystem, then a better solution is to encrypt the data using a key stored (only) in another client side cookie. That way you completely eliminate the storage of unprotected data on your server. (note that suhosin's encrypted sessions use a key derived from data about the client and a static key stored on the same host - this is significantly less secure than a randomly generated key). Here's one I prepared earlier.

如果仅想在gc_maxlifetime过期后阻止访问,则应考虑将过期会话视为丢失的自定义会话处理程序.也就是说,它实际上并没有在到期时注销,但是任何后续请求都无法再与该会话相关联. Stackable会话处理程序示例中的安全层实现了这种控制.

If you merely want to prevent access after the gc_maxlifetime has expired, you should consider a custom session handler which treats a stale session as missing. i.e. it doesn't really logout at expiry, but any subsequent requests can no longer be associated with the session. The security layer in the Stackable session handler examples implements such a control.

OTOH,如果您想在事件监听器中使用会话中的数据,那就是另一回事了-您当然无法使用Suhosin或我的加密来处理数据.但是,更复杂的是,数据的(默认)格式与其他地方使用的格式不同.您需要使用 session_encode ()和 session_decode ().前者将仅从$ _SESSION数组中读取数据,因此在会话上进行窃听需要对session_id()session_start()进行仔细的转换. session_decode()但是会很乐意转换您扔给它的任何东西.

OTOH if you want to use data from within the session in your event listener, then that's a different story - you certainly won't be able to use either Suhosin's or my encryption for the data. But a further complication is that the (default) format for the data is different from that used elsewhere. You need to use session_encode() and session_decode(). The former will only read data from the $_SESSION array so eavesdropping on sessions requires some careful subversion of session_id() and session_start(). session_decode() however will happily convert anything you throw at it.

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

In recent versions of PHP you can specify a different function pair to use for serialization/deserialization.

在考虑将要读取会话文件中数据的会话垃圾收集器时,考虑__wakeup()方法的潜在影响非常重要.与此相关的是,要求处理此类垃圾回收的进程必须与创建会话数据的原始PHP进程在相同的uid下运行(否则,您将拥有特权升级后门).但是,如果会话存储基础结构是基于文件的,那么无论如何都需要这样做.

It is vitally important to consider the potential impact of __wakeup() methods when considering a session garbage collector which is going to read the data in the session files. Related to this is a requirement that the process which handles such garbage collection runs under the same uid as the original PHP process which created the session data (otherwise you have a privilege escalation backdoor). But if the session storage substrate is file-based then that would need to be the case anyway.

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

There are implementations of session data deserializer written in languages other than PHP which would provide protection against __wakeup() attacks (try Google) although that might be overkill to solve the problem and they are probably not being actively maintained. If this is a concern then a more appropriate solution might be to use the WDDX (xml) serializer and use a conventional XML parser to read the data back in your GC engine.

如果您正在使用本机处理程序进行正常的数据读取和写入,但要实现自己的垃圾收集器,则将需要代码将session_id映射到文件路径.如果您遵循我上面提到的PHP类的链接,您将看到几个会话处理程序的纯PHP实现,包括与本机处理程序兼容的会话处理程序.

If you are using the native handler for normal reading and writing of the data but want to implement your own garbage collector then you're going to need code to map the session_id to a file path. If you follow the link I gave to the PHP classes above, you'll see pure PHP implementation of several session handlers, including ones which are compatible with the native handler.

但是我强烈建议您在选择删除时重新读取会话数据之前,用其他所有方法来解决潜在的问题.

But I would strongly encourage you to exhaust every other avenue for solving whatever the underlying problem is before choosing to read back session data at the time of deletion.

这篇关于PHP:如何检测会话是否自动过期?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆