Предупреждение PHP 7.2: невозможно изменить имя сеанса, когда сеанс активен

Поскольку PHP на нашем сервере был обновлен до 7.2 с 7.0. Я получаю следующее предупреждение (которое приводит к ошибке), если выполняется новое развертывание. Причина, вероятно, в том, что старые сеансы становятся недействительными после развертывания.

Предупреждение: 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. К сожалению, ответа тоже нет: - /


person Blackbam    schedule 07.12.2017    source источник
comment
Проверка if(session_id()) {} предполагает, что destroyAbsolute() ожидает, что несколько раз session_start() был вызван, а иногда нет. Ваш вызов session_name() должен следовать той же логике.   -  person Álvaro González    schedule 07.12.2017
comment
Комментарий Должен быть вызван после session_start противоречит документации session_name(), вам нужно вызвать session_name() [...] перед session_start(). Я предполагаю, что этот код никогда не удалял сеанс с именем self::$name.   -  person Roland Starke    schedule 07.12.2017
comment
@RolandStarke В соответствии с документами имя_сессии также может быть установлено на УСТАНОВИТЬ или ВЫБРАТЬ имя текущего сеанса. Можете ли вы дать ссылку на документы, так как я не могу найти, где это задокументировано?   -  person Blackbam    schedule 07.12.2017
comment
php.net/manual/en/function.session-name.php: Имя сеанса сбрасывается до значения по умолчанию, сохраненного в session.name во время запуска запроса. Таким образом, вам нужно вызывать session_name () для каждого запроса (и до того, как будут вызваны session_start () или session_register ()).   -  person Roland Starke    schedule 07.12.2017
comment
С какой версии это было обновлено?   -  person Funk Forty Niner    schedule 07.12.2017
comment
@ Fred-ii - начиная с версии 7.0. Но похоже, что проблема никогда не возникала раньше.   -  person Blackbam    schedule 07.12.2017
comment
TBH, я никогда не устанавливал 7, но PHP - это в основном PHP, как ни крути. Однако проверьте, внесло ли обновление какие-либо изменения в настройки файлов cookie / сеансов. Я предполагаю, что это может иметь какое-то отношение к включенным / обязательным файлам. Возможно, его использует другой сервис?   -  person Funk Forty Niner    schedule 07.12.2017
comment
@ Fred-ii - Только что нашел документ, подтверждающий, что обработка сеанса изменилась в PHP 7.2 (см. Редактирование). Тем не менее я ищу решение этой проблемы.   -  person Blackbam    schedule 07.12.2017
comment
Что ж, по крайней мере, это шаг в правильном направлении. Вы смотрели последний комментарий на этой странице? github.com/php/php-src/commit/7f196e3 - см. также, если что-то связано с использованием отчетов об ошибках и var_dump()'ing прочего, чтобы узнать, что происходит, а что нет.   -  person Funk Forty Niner    schedule 07.12.2017
comment
Я думал, что session_name можно использовать для изменения имени текущего сеанса и управления несколькими сеансами? Таким образом, он должен быть вызван во время работы сеанса, чтобы впоследствии выбрать другой сеанс или запустить новый сеанс с заданным именем с помощью session_start (). Должен ли я сообщать об ошибке PHP или они просто отказались от концепции нескольких сеансов?   -  person Blackbam    schedule 07.12.2017
comment
Использование машина назад и если вернуться в прошлое (2001 год), то можно найти ту же цитату. [...] перед session_start () или session_register (). Так что я считаю, что это не новая функция. возможно, в предыдущих версиях он не работал тихо, а теперь возникает ошибка. Не могли бы вы закрыть текущий сеанс и начать новый? как session_write_close(); session_name(self::$name); session_set_cookie_params(...); session_start();?   -  person Roland Starke    schedule 08.12.2017
comment
У меня возникает эта проблема при обновлении до Drupal 7. Все, кто видит это для Drupal, могут посмотреть здесь.   -  person mbomb007    schedule 15.07.2019


Ответы (3)


Я написал отчет об ошибке на php.net, и они объяснили, что это не ошибка. Да, в PHP 7.2 теперь генерируется предупреждение. Однако это никогда не работало должным образом, оно просто не сработало.

Для создания нескольких сеансов необходимо использовать session_id(). Взгляните на этот связанный вопрос: PHP Как я могу создать несколько сеансов?

session_name(), а также session_set_cookie_params() всегда бессмысленны, если сеанс уже запущен.

Исходный ответ можно найти здесь: https://bugs.php.net/bug.php?id=75650&thanks=2

person Blackbam    schedule 09.12.2017

У меня была похожая проблема, но я наконец нашел способ ее решить. Приведенный ниже код был моим первым подходом, который дал мне ошибки.

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() непосредственно перед началом сеанса и проверяю, существует ли уже сеанс, прежде чем сделать это.

person Miracool    schedule 10.03.2018

TL; DR: если сеанс существует, используйте setcookie(session_name(), session_id(), ...), иначе используйте session_set_cookie_params(...)

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

Поскольку PHP Session Control не обрабатывает время жизни сеанса правильно при использовании session_set_cookie_params (), нам нужно что-то сделать, чтобы изменить время истечения сеанса каждый раз, когда пользователь посещает наш сайт. Итак, вот в чем проблема.

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

Этот код не изменяет время жизни сеанса, когда пользователь возвращается на наш сайт или обновляет страницу. Сессия истечет через $ life секунд, независимо от того, сколько раз пользователь запрашивает страницу. Поэтому мы просто перезаписываем файл 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']
            );
        }
person Jayen    schedule 14.08.2019