23

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

警告:session_name():在第 137 行的 /var/www/html/model/login/lib/Session.class.php 中的会话处于活动状态时无法更改会话名称

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

警告:无法修改标头信息 - 标头已由 /var/www/html/model/login/lib/Session.class.php:137 中的 /var/www/html/model/login/lib/ 发送第 142 行的 Session.class.php

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

4

4 回答 4

15

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

于 2017-12-09T17:50:38.990 回答
5

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

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()会话,并在此之前测试会话是否已经存在。

于 2018-03-10T21:32:49.300 回答
2

TLDR:如果会话存在,则使用setcookie(session_name(), session_id(), ...)else 使用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']
            );
        }
于 2019-08-14T01:40:22.700 回答
0

你好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']
            );
        }
于 2021-12-03T09:48:41.527 回答