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

56,317

Solution 1

I have done a bug report at php.net and they explained that this is not a bug. Yes in PHP 7.2 a warning is generated now. However this never worked as intended, it just failed silently.

For creating multiple sessions it is required to use session_id(). Have a look at this related question: PHP How can I create multiple sessions?

session_name() as well as session_set_cookie_params() are always nonesense if the session is already running.

For the original answer have a look here: https://bugs.php.net/bug.php?id=75650&thanks=2

Solution 2

I had a similar problem but finally found a way through. The code below was my first approach that gave me errors.

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();
    }
}

Now Earlier versions of php overlooked our mistake(We were practically renaming and giving a session that already exists properties which is very wrong. So how did i solve this problem?

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();
         }    
    }

I now bound the session_set_cookie_params() just before session start and I test if the session already exists before doing so.

Solution 3

TLDR: if the session exists, use setcookie(session_name(), session_id(), ...) else use 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.

My solution:

Originally:

        $cookieParams = session_get_cookie_params();

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

Now:

        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']
            );
        }
Share:
56,317

Related videos on Youtube

Blackbam
Author by

Blackbam

Hello! My name is David. I have studied Software Engineering &amp; Internet Computing at the Vienna University of Technology. I am a passionate lead developer, enterprise software engineer and senior web developer. Are you looking for a smart, creative and open-minded IT professional who loves new challenges? Hire me! Especially for complex high-quality Symfony, Laravel, Pimcore or WordPress projects. Be free to contact me via my website or Stack Overflow Careers. Author of a useful general purpose PHP toolkit.

Updated on July 09, 2022

Comments

  • Blackbam
    Blackbam almost 2 years

    Since PHP on our server was upgraded to 7.2 from 7.0. I am getting the following warning (which leads to error) if a new deployment is done. The reason is probably, that old sessions get invalid after deployment.

    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

    It seems like PHP 7.2 got more strict in the context of session sin a certain context. The server seems to recognize the invalid sessions and tries to destroy those. This is part of the Session 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();
        }
    }
    

    What has changed in PHP regarding sessions?

    Why is it not allowed to set a session name if another session is active (according to the docs with session_name I could change sessions and start multiple sessions)?

    And how may I destroy the running session appropriately?

    Doing further research I also have found the following discussion on GitHub (https://github.com/Icinga/icingaweb2/issues/3185). They confirm that this error was introduced with PHP 7.2. Unfortunatly there is also no answer :-/

    • Álvaro González
      Álvaro González over 6 years
      The if(session_id()) {} check suggests that destroyAbsolute() expects that some times session_start() has been called and some times it hasn't. Your call to session_name() should then follow the same logic.
    • Roland Starke
      Roland Starke over 6 years
      The comment "Must be called after session_start" contradics the docs of session_name() "you need to call session_name() [...] before session_start()". I assume this code never deleted the session with the name self::$name.
    • Blackbam
      Blackbam over 6 years
      @RolandStarke According to the docs session_name also can be set to SET or CHOOSE the name of the current session. Can you link to the docs as i can not find where this is documented?
    • Roland Starke
      Roland Starke over 6 years
      php.net/manual/en/function.session-name.php: "The session name is reset to the default value stored in session.name at request startup time. Thus, you need to call session_name() for every request (and before session_start() or session_register() are called)."
    • Funk Forty Niner
      Funk Forty Niner over 6 years
      From which version was this upgraded from?
    • Blackbam
      Blackbam over 6 years
      @Fred-ii- From 7.0. But it seems like the problem never has ocurred before.
    • Funk Forty Niner
      Funk Forty Niner over 6 years
      TBH, I never installed 7 but PHP is basically "PHP", any which way you slice it. However, check to see if the upgrade made any modifications to the cookie/sessions settings. This could have something to do with included / required files, I'm guessing though. Possibly another service using it?
    • Blackbam
      Blackbam over 6 years
      @Fred-ii- Just found a document which confirms that session handling has changed in PHP 7.2 (see edit). Still I am looking for a solution to this.
    • Funk Forty Niner
      Funk Forty Niner over 6 years
      Well, least that's a step in the right direction. Did you have a look at the last comment in that page? The github.com/php/php-src/commit/7f196e3 - See also if anything comes of using error reporting and var_dump()'ing stuff, to see what's happening or not.
    • Blackbam
      Blackbam over 6 years
      I thought session_name could be used for changing the current session name and manage multiple sessions? So it should be callable while a session is running in order to select another session or start a new session with the given name with session_start() afterwards. Should I report a PHP bug or did they just drop the concept of multiple sessions?
    • Roland Starke
      Roland Starke over 6 years
      Using the way back machine and going as far back as possible (2001) you can find the same quote. "[...] before session_start() or session_register()". So i asume its not a new feature. maybe in previous versions it failed silent and now there is an error. Could you close the current session and start a new one? like session_write_close(); session_name(self::$name); session_set_cookie_params(...); session_start();?
    • mbomb007
      mbomb007 almost 5 years
      I get this issue when upgrading to Drupal 7. Anyone else seeing this for Drupal can look here.