如何判断会话是不是处于活动状态? [复制]
Posted
技术标签:
【中文标题】如何判断会话是不是处于活动状态? [复制]【英文标题】:How to tell if a session is active? [duplicate]如何判断会话是否处于活动状态? [复制] 【发布时间】:2011-04-16 20:18:10 【问题描述】:根据请求,您可以通过几种不同的方式判断会话是否已启动,例如:
$isSessionActive = (session_id() != "");
或者:
$isSessionActive = defined('SID');
但是,如果您启动会话,然后关闭它,这两种方法都会失败; session_id()
将返回前一个会话的 ID,而 SID
将被定义。同样,此时调用session_start()
将生成E_NOTICE
,如果您已经有一个活动会话。有没有一种健全的方法来检查会话当前是否处于活动状态,而不必求助于输出缓冲、闭嘴操作符 (@session_start()
) 或其他与 hacky 一样的东西?
编辑:我写了一个补丁来尝试将此功能包含在 PHP 中:http://bugs.php.net/bug.php?id=52982
编辑 2011 年 8 月 29 日:PHP 5.4 添加了新功能以解决此问题:"Expose session status via new function, session_status"
// as of 8/29/2011
$isSessionActive = (session_status() == php_SESSION_ACTIVE);
编辑 12/5/11:session_status() 在 PHP 手册上。
【问题讨论】:
这可能有点骇人听闻:session_is_active()
,但至少我发现了一些东西。无论如何感谢您的错误报告,很高兴看到这个问题在 5.4 中得到解决。
关于 5.4 的添加仍然是一个相关的问题,因为我刚刚推到 5.3 的盒子,发现 session_status()
不见了!
这很奇怪,因为它确实存在于我的 5.4 版本中。你是说你用的是5.3还是5.4?它是自定义的还是预构建的 PHP 二进制文件?在phpinfo()
,你有“会话”部分吗?在行动:codepad.viper-7.com/PiZmcw
【参考方案1】:
查看对原始问题的修改;基本上,PHP 5.4 及更高版本现在有一个名为session_status()
的函数来解决这个问题!
"Expose session status via new function, session_status" (SVN Revision 315745)
如果您在 PHP 5.4 之前的版本中需要此功能,请参阅hakre's answer。
【讨论】:
【参考方案2】:您需要检查多个位置以验证会话是否处于活动状态:
1- cookie 存在且未过期 2- 底层会话存储机制(文件系统或数据库)有一条匹配cookie的记录。
【讨论】:
我认为您误解了目标/意图。 也许是的。我更习惯于处理具有自定义功能的会话。最好将会话封装到一个类中,以便在调用析构函数或调用 session_write_closed 成员函数时更新该类中的布尔标志,显示是否处于活动状态。 这是为了避免Notice: A session had already been started - ignoring session_start()
。这个错误有更多关于用例的信息:bugs.php.net/bug.php?id=52982【参考方案3】:
我通过在各种会话创建/关闭/销毁函数周围添加几个包装函数来解决这个问题。基本上:
function open_session()
session_start();
$_SESSION['is_open'] = TRUE;
function close_session()
session_write_close();
$_SESSION['is_open'] = FALSE;
function destroy_session()
session_destroy();
$_SESSION['is_open'] = FALSE;
function session_is_open()
return($_SESSION['is_open']);
Hackish,但完成了我所需要的。
【讨论】:
嗯,这也是我选择的解决方案...替代方案可能是实现一个会话写入处理程序,该处理程序修改一个内部标志,然后您可以检查它,但这会有点打败了它自己的目的,因为它必须在一开始就被定义。 在 session_close 函数中有一个杂散的大括号,它需要是一个分号。所以不会让我编辑,因为没有足够的字符需要编辑。 ://【参考方案4】:这是一个很好的替代品,当您迁移到 5.4 时不会破坏任何东西:
if(!function_exists('session_status'))
function session_active()
return defined('SID');
else
function session_active()
return (session_status() == PHP_SESSION_ACTIVE);
【讨论】:
正如我在最初的问题中所说,这是一个不充分的解决方案;如果您先调用session_start()
,然后再调用session_write_close()
,那么即使会话未打开,也会调用defined("SID") === true
。这种技术只能确定会话是否在请求周期内启动——而不能确定一个会话当前是否打开。它可能适用于某些用例,但不能替代 session_status()
。【参考方案5】:
我也遇到了这个问题,$_SESSION
中的设置不适合我。对于 PHP 5.3.8:
-
如果任何会话已随请求启动,
define('SID')
将返回 FALSE
,并且 $_SESSION
未设置。
这与session_id()
是否用于设置会话ID 无关。
在第一个session_start()
之后,定义了SID
,并将$_SESSION
设置为一个空数组。
session_destroy()
确实取消了 session_id()
的设置,那么它是一个空字符串。 SID
将保持定义(并设置为之前的值,可能是一个空字符串)。 $_SESSION
保持不变。下次调用 session_start
时,它将被重置/填充。
在这些状态下,尤其是当session_id()
可以在其间调用以设置下一个 会话的ID 时,不可能通过SID
、$_SESSION
安全地确定会话状态和session_id()
。
“尝试”session_start()
(例如@
)可能并没有真正的帮助,因为这会改变会话状态并改变$_SESSION
的内容(如果 cookie 是不是请求的一部分)。这不适合我的情况。
在运行测试时,我遇到了这样的行为,即当会话处于活动状态时,您无法尝试更改 session.serialize_handler
的 ini 设置,即使您将其设置为相同的值也是如此。 session.use_trans_sid
Docs 也是如此,它更轻量级。这导致我使用以下功能:
/**
* @return bool
*/
function session_is_active()
$setting = 'session.use_trans_sid';
$current = ini_get($setting);
if (FALSE === $current)
throw new UnexpectedValueException(sprintf('Setting %s does not exists.', $setting));
$result = @ini_set($setting, $current);
return $result !== $current;
据我所知,该错误仅检查活动会话状态(未禁用),因此禁用会话时不应返回误报。
为了让这个函数与 PHP 5.2 兼容,需要稍作修改:
/**
* @return bool
*/
function session_is_active()
$setting = 'session.use_trans_sid';
$current = ini_get($setting);
if (FALSE === $current)
throw new UnexpectedValueException(sprintf('Setting %s does not exists.', $setting));
$testate = "mix$current$current";
$old = @ini_set($setting, $testate);
$peek = @ini_set($setting, $current);
$result = $peek === $current || $peek === FALSE;
return $result;
一些sandbox。
【讨论】:
虽然这仍然有点“hacky”,但您的技术给我留下了深刻的印象。我的想法是问题的某些属性可以用来推断(例如您在这里所做的事情),我只是无法找到它们。非常好! 另外,沙箱是您的网站吗?操作码分析很不错。 不,那不是我的网站,但我也喜欢它。 :) 现在我不确定该 hack 是否适用于 PHP 5.1(我可能需要它)。 @Salathe 非常友善,并根据各种 PHP 5.1 版本 (gist.github.com/1265615#gistfile1.txt) 测量例程,看起来对向后兼容非常有用。【参考方案6】:Ken,如果会话被破坏,$_SESSION 数组应该不可用......或者至少,你的值应该是未设置的。因此,理论上(未经测试)您应该能够检查数组中的值以了解当前是否设置了任何内容。
【讨论】:
session_destroy()
或 session_write_close()
未设置 $_SESSION
。【参考方案7】:
以下代码只为我转储一个 session_id(),而不是两个
session_start();
echo session_id();
session_destroy();
echo session_id();
如果您仍然遇到困难,您可以尝试创建一个变量来检查,当您销毁会话时您会销毁该变量。
session_start();
$_SESSION['intialized'] = 'This will not print';
$_SESSION = array(); // Unset all variables
session_destroy();
echo $_SESSION['initialized']; // No output
【讨论】:
但是如果你使用 session_write_close(),会话已经关闭,但是 $_SESSION 数据仍然存在,我认为这就是 OP 的意思......你如何检查会话文件本身是否还在使用吗? 是的,您基本上发布了与我相同的解决方案,在关闭它之前设置一个变量(以任何方式)并检查该变量...以上是关于如何判断会话是不是处于活动状态? [复制]的主要内容,如果未能解决你的问题,请参考以下文章