前言
在做某个需求时,将 token
存在了 SESSION
里,然而呢,SESSION
是存在 Redis
里的。在检查这个 token
是否正确时,却发现,时而正确,时而错误。
检查了从 SESSION
里取出的值,发现里面的内容会有几率的不同。
于是,查看了 Redis
里的值,发现是存在,并且正确的。查看了 /var/lib/php/sessions
里的值,发现是存在,并且错误的。与之前打出的值一样,这,我懵逼了。
于是漫长的 BUG
之路开始了。
原因
检查了很久,还是不知原因,便请来了华仔(技术牛人)。
一开始,我们的方向是:因为配置的问题,导致 Redis
读的库混乱了。检查之后发现,配置没有任何问题。
然后想到了,我的所有站点都在一个系统里,是不是因为其他站点引起的。试验之后发现,果不其然。
当访问了另外一个从文件读取 SESSION
的站点之后,主站点就会取到两种 Redis
。
于是我就怀疑,是 PHP-FPM
的问题,请求结束后,SESSION
并没有被销毁。
验证
在主站点的入口文件里,写了一段代码,主要是测试 SESSION
是否有被关闭。
<?php
// ...
$status = session_status();
switch ($status) {
case PHP_SESSION_ACTIVE:
echo 'session is active';
break;
case PHP_SESSION_NONE:
case PHP_SESSION_DISABLED:
echo 'session is not active';
break;
}
exit();
// ...
检测发现,有几率出现 'session is active' 的情况。这说明了,次站点的请求结束后,并没有关闭 SESSION
。 华仔看了一下源码,也证实了这件事情。
最终在 PHP
的官网上看到了这个:
既然问题已经出现,那么,如何解决呢。
解决
次站点在响应给出之前,先关闭 SESSION
,使用 session_write_close()
方法。
同时,主站点在初始化 SESSION
时,可以先关闭 SESSION
再开启,实现如下。
<?php
// ...
$status = session_status();
switch ($status) {
case PHP_SESSION_ACTIVE:
session_write_close();
session_start();
break;
case PHP_SESSION_NONE:
case PHP_SESSION_DISABLED:
session_start();
break;
}
exit();
// ...
这个时候,就可以去自定义会话管理了,无论是存在 Redis
、Memcache
或者 database
里都可以。
总结
很多问题,在多数情况下,是不会出现的。只有做多,才会错多。
然而,错并不可怕,发现并将其改正就好。
-- EOF --
本文转载自IMJCW
原文链接:PHP 两个站点造成的SESSION混乱
网友评论