【问题标题】:PHP 7.2 Warning: "Cannot change session name when session is active"PHP 7.2 警告:“会话处于活动状态时无法更改会话名称”
【发布时间】:2018-05-21 20:55:21
【问题描述】:

由于我们服务器上的 PHP 从 7.0 升级到 7.2。如果完成新部署,我会收到以下警告(这会导致错误)。原因可能是,旧会话在部署后失效。

警告:session_name(): 会话结束时无法更改会话名称 活跃在 /var/www/html/model/login/lib/Session.class.php 第137行

警告:session_set_cookie_params():无法更改会话 cookie 会话处于活动状态时的参数 /var/www/html/model/login/lib/Session.class.php 第 138 行

警告:无法修改标头信息 - 标头已由 (输出开始于 /var/www/html/model/login/lib/Session.class.php:137) 在 /var/www/html/model/login/lib/Session.class.php 第 142 行

似乎 PHP 7.2 在会话上下文中变得更加严格了。服务器似乎识别出无效会话并尝试销毁这些会话。这是 Session 类的一部分:

/**
 * Secure instant destruction of session. Must be called after session_start !
 */
public static function destroyAbsolute() {

    self::checkInit(); // unimportant

    session_name(self::$name); // this is line 137
    session_set_cookie_params(0, COOKIEPATH, null, self::$force_ssl_cookie, true);

    if(session_id()) {
        if (isset($_COOKIE[session_name()])) {
            setcookie(session_name(), "", time() - 42000, COOKIEPATH);
        }
        unset($_COOKIE[session_name()]);
        session_destroy();
    }
}

PHP 在会话方面发生了哪些变化?

如果另一个会话处于活动状态,为什么不允许设置会话名称(根据带有 session_name 的文档,我可以更改会话并启动多个会话)?

我怎样才能适当地销毁正在运行的会话?

做进一步的研究,我还在 GitHub (https://github.com/Icinga/icingaweb2/issues/3185) 上找到了以下讨论。 他们确认 PHP 7.2 引入了此错误。不幸的是也没有答案:-/

【问题讨论】:

  • if(session_id()) {} 检查表明destroyAbsolute() 预计有时session_start() 已被调用,有时则未调用。您对session_name() 的调用应该遵循相同的逻辑。
  • 注释“必须在 session_start 之后调用”与session_name() 的文档相矛盾“你需要在session_start() 之前调用session_name() [...]”。我假设此代码从未删除名称为 self::$name 的会话。
  • @RolandStarke 根据文档 session_name 也可以设置为 SET 或 CHOOSE 当前会话的名称。您可以链接到文档吗,因为我找不到文档记录在哪里?
  • 使用way back machine 并尽可能追溯到(2001 年)您可以找到相同的报价。 “[...] 在 session_start() 或 session_register() 之前”。所以我认为它不是一个新功能。也许在以前的版本中它失败了,现在出现了错误。你能关闭当前会话并开始一个新会话吗?喜欢session_write_close(); session_name(self::$name); session_set_cookie_params(...); session_start();?
  • 我在升级到 Drupal 7 时遇到了这个问题。其他看到 Drupal 的人可以查看here

标签: php session cookies php-7.2


【解决方案1】:

我在 php.net 上做了一个错误报告,他们解释说这不是错误。 是的,在 PHP 7.2 中现在会生成一个警告。但是这从未按预期工作,它只是默默地失败了

要创建多个会话,需要使用session_id()。看看这个相关的问题:PHP How can I create multiple sessions?

session_name()session_set_cookie_params() 如果会话已经在运行,则始终是无意义的。

查看原始答案:https://bugs.php.net/bug.php?id=75650&thanks=2

【讨论】:

    【解决方案2】:

    我遇到了类似的问题,但终于找到了解决办法。下面的代码是我第一个给我错误的方法。

    static function startmysession($lifetime, $path, $domain, $secure, $httponly){
    
        session_set_cookie_params($lifetime, $path, $domain, $secure, $httponly);
        session_regenerate_id(true);
    
        if(!isset($_SESSION)){
            session_start();
        }
    }
    

    现在早期版本的 php 忽略了我们的错误(我们实际上是在重命名并提供一个已经存在属性的会话,这是非常错误的。那么我是如何解决这个问题的呢?

    static function startmysession($lifetime, $path, $domain, $secure, $httponly){      
        if(!isset($_SESSION)){  
             session_set_cookie_params($lifetime, $path, $domain, $secure, $httponly);
             @session_regenerate_id(true);    
                 session_start();
             }    
        }
    

    我现在在会话开始之前绑定session_set_cookie_params(),并在此之前测试会话是否已经存在。

    【讨论】:

      【解决方案3】:

      TLDR:如果会话存在,则使用setcookie(session_name(), session_id(), ...),否则使用session_set_cookie_params(...)

      https://www.php.net/manual/en/function.session-set-cookie-params.php#100657

      由于 PHP 的会话控制不能正确处理会话生命周期 当使用 session_set_cookie_params() 时,我们需要在 为了在每次用户访问我们的时候更改会话到期时间 地点。所以,这就是问题所在。

      <?php
        $lifetime=600;
        session_set_cookie_params($lifetime);
        session_start();
      ?>
      

      此代码不会改变会话的生命周期,当用户 返回我们的网站或刷新页面。会话将过期 $lifetime 秒后,无论用户请求多少次 这页纸。所以我们只是覆盖会话cookie如下:

      <?php
        $lifetime=600;
        session_start();
        setcookie(session_name(),session_id(),time()+$lifetime);
      ?>
      

      现在我们有了相同的会话 cookie,其生命周期设置为 适当的价值。

      我的解决方案:

      原来:

              $cookieParams = session_get_cookie_params();
      
              session_set_cookie_params(
                  $seconds,
                  $cookieParams['path'],
                  $cookieParams['domain'],
                  $cookieParams['secure']
                  );
      

      现在:

              if(isset($_SESSION)) {
                  if ($seconds != 0) {
                      setcookie(session_name(), session_id(), time() + $seconds);
                  } else {
                      setcookie(session_name(), session_id(), $seconds);
                  }
              } else {
                  $cookieParams = session_get_cookie_params();
      
                  session_set_cookie_params(
                      $seconds,
                      $cookieParams['path'],
                      $cookieParams['domain'],
                      $cookieParams['secure']
                  );
              }
      

      【讨论】:

        【解决方案4】:

        你好where文件修改解决方案代码

        if(isset($_SESSION)) {
        if ($seconds != 0) {
                   setcookie(session_name(), session_id(), time() + $seconds);
                    } else {
                        setcookie(session_name(), session_id(), $seconds);
                    }
                } else {
                    $cookieParams = session_get_cookie_params();
        
                    session_set_cookie_params(
                        $seconds,
                        $cookieParams['path'],
                        $cookieParams['domain'],
                        $cookieParams['secure']
                    );
                }
        

        【讨论】:

          猜你喜欢
          • 2020-07-14
          • 1970-01-01
          • 2012-11-19
          • 1970-01-01
          • 2021-10-21
          • 2012-11-12
          • 2015-05-21
          • 2020-04-26
          • 2020-05-31
          相关资源
          最近更新 更多