如何在Yii 1.1.29中通过会话属性查找并销毁指定会话?
Yii 1.1.29 实现通过Access Token查找并销毁会话(SSO登出同步)
核心思路
Yii 1.1的会话存储分为数据库存储(推荐生产环境)和文件存储(默认方式)两种,针对这两种场景分别实现通过access token查找会话和销毁会话的逻辑即可完成SSO登出同步。
方案一:数据库存储会话(高效可靠)
如果站点已配置数据库存储会话,操作更直接:
1. 确认会话表结构
Yii默认的会话表结构可通过迁移生成,格式如下:
CREATE TABLE `session` ( `id` CHAR(32) NOT NULL PRIMARY KEY, `expire` INTEGER, `data` TEXT ) ENGINE=InnoDB;
2. 查找对应会话
解析序列化的会话数据,筛选出包含目标access token的会话ID:
$targetToken = 'abcd'; // IDP传来的待销毁token $matchedSessionIds = []; // 查询所有未过期的会话 $activeSessions = Yii::app()->db->createCommand() ->select('id, data') ->from('session') ->where('expire > :currentTime', [':currentTime' => time()]) ->queryAll(); foreach ($activeSessions as $session) { // 反序列化会话存储的属性数据 $sessionAttributes = unserialize($session['data']); // 假设access token存储在会话的'access_token'字段下,根据实际业务调整 if (isset($sessionAttributes['access_token']) && $sessionAttributes['access_token'] === $targetToken) { $matchedSessionIds[] = $session['id']; break; // 单个token对应单个会话时,找到即可终止遍历 } }
3. 销毁会话
遍历找到的会话ID,删除会话记录并清理关联缓存:
foreach ($matchedSessionIds as $sessionId) { // 删除数据库中的会话记录 Yii::app()->db->createCommand() ->delete('session', 'id = :sid', [':sid' => $sessionId]); // 清理用户登录状态相关缓存(若有) Yii::app()->cache->delete('user_login_status_' . $sessionId); }
方案二:文件存储会话(默认方式)
Yii默认将会话存储在服务器临时目录(可通过php.ini的session.save_path或Yii配置调整):
1. 遍历会话文件查找目标
$targetToken = 'abcd'; $matchedSessionIds = []; $sessionDir = Yii::app()->session->savePath; // 遍历会话目录下的所有会话文件(默认前缀为sess_) $sessionFiles = glob($sessionDir . '/sess_*'); foreach ($sessionFiles as $file) { $sessionContent = file_get_contents($file); if (!$sessionContent) continue; // 反序列化会话数据 $sessionAttributes = unserialize($sessionContent); if (isset($sessionAttributes['access_token']) && $sessionAttributes['access_token'] === $targetToken) { // 提取会话ID(去除文件名前缀sess_) $sessionId = substr(basename($file), 5); $matchedSessionIds[] = $sessionId; break; } }
2. 销毁会话
foreach ($matchedSessionIds as $sessionId) { // 删除会话文件 unlink($sessionDir . '/sess_' . $sessionId); // 清理关联缓存 Yii::app()->cache->delete('user_login_status_' . $sessionId); }
优化建议
- 提前映射token与会话ID:用户登录生成access token时,将token和会话ID存入单独的映射表(如
token_session_map),后续查找只需查询该表,无需遍历所有会话,大幅提升效率。 - 请求合法性校验:IDP发起的登出请求必须做身份验证(如签名校验),防止恶意销毁会话。
- 并发处理:销毁会话时加锁,避免多请求同时操作导致的数据不一致。
内容的提问来源于stack exchange,提问作者Lajos Arpad
相关产品推荐
相关产品推荐

