当定义了会话过期时间时,是否可以在其过期时调用事件监听器?
如果不可能,是否可以运行cron作业来检查会话是否已过期?
注意:我想要一个服务器解决方案。我谈论的是当定义了会话过期时间并且会话因为该期限自动完成时的情况。
当定义了会话过期时间时,是否可以在其过期时调用事件监听器?
如果不可能,是否可以运行cron作业来检查会话是否已过期?
注意:我想要一个服务器解决方案。我谈论的是当定义了会话过期时间并且会话因为该期限自动完成时的情况。
gc_maxlifetime
结束时过期-这只是数据变得符合自动删除条件的时间。没有会话所有者触发随后删除会话的任何操作-这是其他人会话的副作用。当调用session_write_close()
(显式或隐式地由代码结束)时,如果随机数生成器(由相关gc设置调整)产生正确的数字,则PHP将查找超出其TTL的数据并将其删除。如果您想在此时触发操作,则需要打破默认处理程序并应用自己的处理程序。这意味着您不仅必须提供识别和删除会话的机制,还必须确定您的处理程序何时启动以及它应该删除多少个会话-您不希望有runaway process killing your server。在Ubuntu中,session.gc_probability = 0
,它是一个cron作业,执行删除陈旧数据文件的功能。您问题中遗漏的非常重要的信息是删除会话的原因。gc_maxlifetime
过期后阻止访问,你应该考虑一个自定义的会话处理程序,将过期的会话视为丢失。也就是说,它并没有真正注销,但是任何后续请求都无法再与会话关联。Stackable 会话处理程序示例中的安全层实现了这样的控制。session_id()
和session_start()
。然而,session_decode()
可以轻松转换任何您提供的内容。__wakeup()
方法的潜在影响是至关重要的。与此相关的是,处理此类垃圾收集的进程必须在原始PHP进程下运行,该进程创建了会话数据(否则您将拥有特权升级后门)。但是,如果会话存储基质基于文件,那么无论如何都需要这样做。
除了PHP以外,还有其他编程语言编写的会话数据反序列化程序可以防止__wakeup()
攻击(尝试谷歌),尽管这可能过度解决问题,而且它们可能没有得到积极维护。如果这是一个问题,那么更合适的解决方案可能是使用WDDX(XML)序列化器,并使用常规XML解析器在GC引擎中读取数据。
如果您正在使用本机处理程序来正常读写数据,但想要实现自己的垃圾回收器,那么您需要编写将session_id
映射到文件路径的代码。如果您按照我上面给出的PHP类的链接,您会看到纯PHP实现的几个会话处理程序,包括与本机处理程序兼容的处理程序。
但我强烈建议您在选择在删除时读回会话数据之前,耗尽解决基础问题的每一条途径。
<?
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();
}
我在这里做一些假设。
我假设你想要追踪已过期的会话,而且不希望通过数据库或第二个“隐藏”的会话来补充追踪会话数据以确定伪会话何时过期并采取适当措施。
我还假设,在此时防范黑客攻击并不重要。中间人和XSS攻击可以捕获会话ID并将其插入到您的系统中,很难检测到。
这种情况在php中默认由会话cookie处理。我还假设您的会话标识和会话开始也由cookie处理。
实现这种“实时”监测的方式几乎没有,也就是说,保持一个套接字连接到服务器来检测会话过期的时刻。PHP并非为此设计; 安全问题会很多。此外,如果您允许某人通过安全通道远程访问您的服务器,那么为什么一开始要费心使用会话呢?
$sessionCookie = 'myPHPSessCookieName';
$isSessionExpired = false;
if (isset($_COOKIE[$sessionCookie])) {
// check cookie expiry time to show warnings / near expiry behaviours
} else {
// handle missing cookie / session
$isSessionExpired = true;
}
define('SESSION_EXPIRED', $isSessionExpired);
session_start(['name' => $sessionCookie]);
在启动会话之前,必须检查cookie,否则您可能会得到一个错误的结果。
[编辑:JavaScript解决方案]
如果您想产生一个模拟socket的行为,可以使用javascript。客户端浏览器将使用AJAX请求向服务器发送ping来检查其会话状态,一旦检测到会话已过期,您就可以诱导出一个自己选择的行为。注意:当前状态下的javascript基本上是不安全的。所有与数据和安全有关的工作都应尽可能由服务器完成。
client.php:
<script>
$(function(){
var messageElem = $('#selectorForDisplayElementHere');
var timeoutID = null;
var checkSession = function(){
$
.ajax({/* your ajax params: url, data, dataType, method etc. */})
.then(function(response){
messageElem.html(response.html);
if (response.stop === 1) {
clearTimeout(timeoutID);
}
});
};
var timeoutID = setInterval(checkSession, 5000); // Every 5 seconds
});
</script>
ajax.php:
$response = ['html' => '', 'stop' => 0];
if (SESSION_EXPIRED) {
$response ['html'] = '<b>Your session has expired. Please log in again.</b>';
$response['stop'] = 1;
}
echo(json_encode($response));
这是一个非常简单的处理系统,可以轻松地增强各种功能。它使用普及率很高的jQuery库和标准的php和html/javascript功能。
看起来你想在服务器端在特定时间清除会话。你需要做的是定义自己的自定义会话处理程序,并将会话数据放入您完全控制的系统中。因此,假设您将会话处理移动到数据库中,则所有会话数据都完全由您控制。下面是一个缩写的自定义会话处理程序。
class Sessions implements \SessionHandlerInterface {
/**
* Write Session Data
* @param string $id Session ID to delete
* @param string $data Data to write into the session
*/
public function write($id, $data) {
$time = time() + 3600; // 1 hour for the sake of example
$sql = 'REPLACE INTO your_session_table
SET session_id = ?,
data = ?,
expires = ?';
$this->db->query($sql);
$prep = $this->db->prepare($sql);
$prep->bind_param('ssi', $id, $data, $time);
$prep->execute();
}
}
在这里,您可以运行自己的清理脚本。我建议您使用中间内存存储(memcached, Redis等),这样您就不必每次都从数据库中加载。当您运行清理脚本时,您需要清除它(即拉取所有即将过期的会话并从缓存中删除)。但是,一个简单的SQL语句(例如,每5分钟运行一次的cron作业)可以按需清除会话。
DELETE FROM your_session_table
WHERE expires < now();
Login.php
。<?php
session_start();
if(...){
// success
$_SESSION['logged_time'] = time();
}
?>
现在在另一个页面检查会话是否已过期。
示例:Index.php
<?php
session_start();
$login_session_duration = 60; // 1 minute
if($_SESSION['logged_time']){
if(((time() - $_SESSION['logged_time']) > $login_session_duration)){
echo 'session expired';
// session will be exired after 1 minutes
}else{
echo 'session alive';
}
}
?>
$current_time=time();
获取在ini文件中设置的会话过期时间。
$maxlifetime = ini_get("session.gc_maxlifetime");
如果session_cache_expire()返回0,则说明您的会话已结束。可能需要在操作处理程序上实现此功能。这不会在服务器上设置您的会话,只是解决了客户端浏览器知道何时过期的问题,这就是您的自动检测...