2

I wrote this code to manage the sessions so that they should expire when browser is closed or if the user is inactive for a defined time (2 hours). However it seems that the sessions are expiring after 40 minutes of inactivity, and i really dont get how's this possible. If my code is failing, i would expect that they should last 1440 seconds (24 minutes).

define("MY_SESSION", "mysession");
define("SESSION_DURATION", 7200);
function my_session_start() {
    if (session_status() != PHP_SESSION_NONE)
        return;
    ini_set('session.gc_maxlifetime', SESSION_DURATION);
    ini_set('session.cookie_lifetime', 0);
    session_set_cookie_params(0);
    session_name(MY_SESSION);
    session_start();
    if ((!isset($_SESSION['EXPIRES'])) || ($_SESSION['EXPIRES'] < time())) {
        $_SESSION = array();
        session_unset();
        session_destroy();
        session_start();
    }
    $_SESSION['EXPIRES'] = time() + SESSION_DURATION;
    if (isset($_SESSION['REGENERATE'])) {
        $_SESSION['REGENERATE']++;
        if ($_SESSION['REGENERATE'] >= mt_rand(90,100)) {
            $_SESSION['REGENERATE'] = 0;
            session_regenerate_id(true);
        }
    }
    else {
        $_SESSION['REGENERATE'] = 0;
        session_regenerate_id(true);
    }
}

I placed my_session_start() in each PHP file. I'm on a shared server but ini_set() is not blocked, and by launching a phpinfo() after my_session_start() i can see that session.gc_maxlifetime local value is being set to 7200 (while master value is 1440). session.gc_probability and session.gc_divisor are left at their default values (respectively 1 and 100). I'm also regenerating session ids on a random base of 90-100 page loads / AJAX calls but that doesnt matter since i tried also to comment out that part and it did not solve the problem.

So, am i doing something wrong with my code? Where does that minutes amount come from, i mean why 40 minutes?

Fabius
  • 506
  • 9
  • 22
  • 1
    Check this answer on [how to expire PHP session after 30m][1]. [1]: http://stackoverflow.com/questions/520237/how-do-i-expire-a-php-session-after-30-minutes – Alberto Feb 14 '15 at 02:29
  • 1
    That's almost what i'm doing with my code and the problem certainly doesnt come from divisor and probability since i tried at least 5 times: 39 minutes of inactivity -> session alive, 41 minutes of inactivity -> session dead. Still wondering why, and why 40 minutes – Fabius Feb 14 '15 at 02:33
  • 40-minute mystery solved: Based on the comment in the attached article, I watched the 'session file' on my host's server. After 40 minutes, it vanished. Being on a shared account, it would appear that our web hosts have custom cron jobs set on these session folders. And that explains why redirecting the `save_path` works---it takes the session files out from under their cron jobs https://solutionfactor.net/blog/2014/02/08/implementing-session-timeout-with-php/#comment-7448 (and yields some added security to boot https://canvas.seattlecentral.edu/courses/980464/pages/10-advanced-php-sessions). – Keith DC May 16 '20 at 00:54

1 Answers1

2

So i finally figured out how to fix this issue. The solution was to change the session files saving folder:

ini_set('session.save_path', "/the/new/path/to/sessions/"); //DEFAULT: /var/lib/php5

Doing this implies that the session files might be viewed, so i added .htaccess file containing:

deny from all

inside "/the/new/path/to/sessions/" folder. So nothing can be viewed from outside the server.

Also, i had to add a new session garbage collection function:

function clear_old_sessions() {
    $folder = "/the/new/path/to/sessions/";
    $files = scandir($folder);
    for ($i = 0; $i < count($files); $i++) {
        $file = $folder . $files[$i];
        if (is_file($file))
            if (substr($files[$i], 0, 5) == "sess_")
                if ((filemtime($file) + SESSION_DURATION) < time()) // SESSION_DURATION previosuly defined as 7200 (seconds)
                            unlink($file);
    }
}
user_4685247
  • 2,878
  • 2
  • 17
  • 43
Fabius
  • 506
  • 9
  • 22
  • Although your solution worked for me as well (and thank you for posting this 5 years ago!), it was part of a bigger puzzle with other pieces provided by the links herein. As an aside, I also read it's more secure for the relocated `save_path` to be outside of web access, ergo created above---such as a sibling to---the public_html folder. https://solutionfactor.net/blog/2014/02/08/implementing-session-timeout-with-php/ https://canvas.seattlecentral.edu/courses/980464/pages/10-advanced-php-sessions and of course: https://www.php.net/manual/en/session.configuration.php – Keith DC May 16 '20 at 00:54
  • 1
    Sure, if your host lets you work also outside of public_html folder, session files should be placed outside. Ate the time i wrote my code unfortunately i had to work on a shared hosting that did not let me have access to anything outside public_html so i had to place the folder containing session files inside of it and work around the security issues with an .htaccess file – Fabius Jul 13 '20 at 13:18