如何判断会话是否有效?

时间:2010-09-24 15:05:24

标签: php session

根据请求,您可以通过几种不同的方式判断会话是否已启动,例如:

$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

编辑8/29/2011:添加到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手册上。

7 个答案:

答案 0 :(得分:22)

查看原始问题的编辑;基本上,PHP 5.4及以上版本现在有一个名为session_status()的函数来解决这个问题!

"Expose session status via new function, session_status" (SVN Revision 315745)

如果您需要在PHP 5.4之前的版本中使用此功能,请参阅hakre's answer

答案 1 :(得分:15)

我通过在各种会话创建/关闭/销毁功能周围添加几个包装函数来解决这个问题。基本上是:

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,但完成了我需要的东西。

答案 2 :(得分:10)

我也遇到了这种情况,$_SESSION中的设置对我来说不是一个选项。对于PHP 5.3.8:

  1. 如果已针对请求启动任何会话,define('SID')将返回FALSE,并且$_SESSION未设置。
  2. 无论是否session_id()用于设置会话ID,这都是独立的。
  3. 在第一个session_start()之后,SID被定义,$_SESSION被设置为空数组。
  4. session_destroy()取消设置session_id(),然后是空字符串。 SID将保持定义(并设置为之前的值,可能是空字符串)。 $_SESSION保持不变。它将在下次调用session_start时重置/填充。
  5. 使用这些状态,尤其是可以在两者之间调用session_id()来设置下一个会话的ID时,无法使用SID安全地确定会话状态,$_SESSIONsession_id()

    使用session_start()“尝试”(例如使用@)可能不太有用,因为这会更改会话状态并更改$_SESSION的内容(并添加一组 - 如果cookie不是请求的一部分,则为cookie头。这不符合我的情况。

    当我运行测试时,我遇到了这样的行为,即当会话处于活动状态时,您无法尝试更改session.serialize_handler的ini设置,即使您将其设置为相同的值也是如此。对于更轻量级的session.use_trans_sidDocs也是如此。这引出了以下功能:

    /**
     * @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

答案 3 :(得分:5)

以下代码仅为我转储一个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

答案 4 :(得分:1)

这是一个很好的替代品,当你转到5.4时不会破坏东西:

if(!function_exists('session_status')){
    function session_active(){
        return defined('SID');   
    }
}else{
    function session_active(){
        return (session_status() == PHP_SESSION_ACTIVE);   
    }        
}

答案 5 :(得分:0)

Ken,如果会话被销毁,$ _SESSION数组应该不可用......或者至少,你的值应该是未设置的。因此,理论上(未经测试)您应该能够检查数组中的值以了解当前是否设置了任何内容。

答案 6 :(得分:0)

您需要检查多个位置以验证会话是否处于活动状态:

1- cookie存在且未过期 2-基础会话存储机制(文件系统或数据库)具有与cookie匹配的记录。