PHP 7.2 警告:"Cannot change session name when session is active"

PHP 7.2 Warning: "Cannot change session name when session is active"

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

Warning: session_name(): Cannot change session name when session is active in /var/www/html/model/login/lib/Session.class.php on line 137

Warning: session_set_cookie_params(): Cannot change session cookie parameters when session is active in /var/www/html/model/login/lib/Session.class.php on line 138

Warning: Cannot modify header information - headers already sent by (output started at /var/www/html/model/login/lib/Session.class.php:137) in /var/www/html/model/login/lib/Session.class.php on line 142

似乎 PHP 7.2 在特定上下文中的会话上下文中变得更加严格。服务器似乎识别出无效会话并试图销毁它们。这是会话的一部分 class:

/**
 * 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 中引入的。不幸的是,也没有答案:-/

我在 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

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

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() 并且我在这样做之前测试会话是否已经存在。

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

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

As PHP's Session Control does not handle session lifetimes correctly when using session_set_cookie_params(), we need to do something in order to change the session expiry time every time the user visits our site. So, here's the problem.

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

This code doesn't change the lifetime of the session when the user gets back at our site or refreshes the page. The session WILL expire after $lifetime seconds, no matter how many times the user requests the page. So we just overwrite the session cookie as follows:

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

And now we have the same session cookie with the lifetime set to the proper value.

我的解决方案:

原来:

        $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']
            );
        }

你好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']
            );
        }