26

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 :-/

12
  • 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. Commented Dec 7, 2017 at 17:19
  • 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. Commented Dec 7, 2017 at 17:22
  • @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? Commented Dec 7, 2017 at 17:27
  • 1
    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();? Commented Dec 8, 2017 at 7:22
  • 1
    I get this issue when upgrading to Drupal 7. Anyone else seeing this for Drupal can look here. Commented Jul 15, 2019 at 18:44

4 Answers 4

18

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

Sign up to request clarification or add additional context in comments.

Comments

6

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.

Comments

4

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

Comments

0

hello where file modify the solution code

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.