Categories
cookies php session

How do I expire a PHP session after 30 minutes?

1147

I need to keep a session alive for 30 minutes and then destroy it.

3

  • 38

    Please note that at least two settings are crucial to setting the session time, and maybe three. The two certainly crucial ones are session.gc_maxlifetime and session.cookie_lifetime (where 0 is not the same as some long number). For complete, 100% certainty of allowing long times, it may also be necessary to set the session.save_path, due to varying OS-controled cleanup time on the /tmp directory where session files get stored by default.

    – Kzqai

    Apr 7, 2011 at 8:04


  • 1

    I don’t understand why you want to expire the session. If you worry the user leaves his computer without logging out, and an unauthorized user takes over his computer, the session expiration on your site will not prevent the hijacker access the victim’s files on the disk.

    – Gqqnbig

    Jan 10, 2018 at 21:53


  • @Gqqnbig: not every session is set for the reasons you are indirectly suggesting here

    Nov 15, 2021 at 10:35

1756

You should implement a session timeout of your own. Both options mentioned by others (session.gc_maxlifetime and session.cookie_lifetime) are not reliable. I’ll explain the reasons for that.

First:

session.gc_maxlifetime
session.gc_maxlifetime specifies the number of seconds after which data will be seen as ‘garbage’ and cleaned up. Garbage collection occurs during session start.

But the garbage collector is only started with a probability of session.gc_probability divided by session.gc_divisor. And using the default values for those options (1 and 100 respectively), the chance is only at 1%.

Well, you could simply adjust these values so that the garbage collector is started more often. But when the garbage collector is started, it will check the validity for every registered session. And that is cost-intensive.

Furthermore, when using PHP’s default session.save_handler files, the session data is stored in files in a path specified in session.save_path. With that session handler, the age of the session data is calculated on the file’s last modification date and not the last access date:

Note: If you are using the default file-based session handler, your filesystem must keep track of access times (atime). Windows FAT does not so you will have to come up with another way to handle garbage collecting your session if you are stuck with a FAT filesystem or any other filesystem where atime tracking is not available. Since PHP 4.2.3 it has used mtime (modified date) instead of atime. So, you won’t have problems with filesystems where atime tracking is not available.

So it additionally might occur that a session data file is deleted while the session itself is still considered as valid because the session data was not updated recently.

And second:

session.cookie_lifetime
session.cookie_lifetime specifies the lifetime of the cookie in seconds which is sent to the browser. […]

Yes, that’s right. This only affects the cookie lifetime and the session itself may still be valid. But it’s the server’s task to invalidate a session, not the client. So this doesn’t help anything. In fact, having session.cookie_lifetime set to 0 would make the session’s cookie a real session cookie that is only valid until the browser is closed.

Conclusion / best solution:

The best solution is to implement a session timeout of your own. Use a simple time stamp that denotes the time of the last activity (i.e. request) and update it with every request:

if (isset($_SESSION['LAST_ACTIVITY']) && (time() - $_SESSION['LAST_ACTIVITY'] > 1800)) {
    // last request was more than 30 minutes ago
    session_unset();     // unset $_SESSION variable for the run-time 
    session_destroy();   // destroy session data in storage
}
$_SESSION['LAST_ACTIVITY'] = time(); // update last activity time stamp

Updating the session data with every request also changes the session file’s modification date so that the session is not removed by the garbage collector prematurely.

You can also use an additional time stamp to regenerate the session ID periodically to avoid attacks on sessions like session fixation:

if (!isset($_SESSION['CREATED'])) {
    $_SESSION['CREATED'] = time();
} else if (time() - $_SESSION['CREATED'] > 1800) {
    // session started more than 30 minutes ago
    session_regenerate_id(true);    // change session ID for the current session and invalidate old session ID
    $_SESSION['CREATED'] = time();  // update creation time
}

Notes:

  • session.gc_maxlifetime should be at least equal to the lifetime of this custom expiration handler (1800 in this example);
  • if you want to expire the session after 30 minutes of activity instead of after 30 minutes since start, you’ll also need to use setcookie with an expire of time()+60*30 to keep the session cookie active.

31

  • 3

    How could you alter this if you wanted to check “inactive time”? In other words, the user logs in, and as long as they continue to use the site, it will not log them out. However if they are inactive for 30 mins it will log them out?

    Aug 9, 2010 at 16:29

  • 14

    @Metropolis: Use something like $_SESSION['LAST_ACTIVITY'] similar to $_SESSION['CREATED'] where you store the time of the last activity of the user but update that value with every request. Now if the difference of that time to the current time is larger that 1800 seconds, the session has not been used for more than 30 minutes.

    – Gumbo

    Aug 9, 2010 at 16:37

  • 5

    @Metropolis: session_unset does the same as $_SESSION = array().

    – Gumbo

    Aug 9, 2010 at 19:06

  • 14

    @Gumbo – I´m a bit confused, shouldn´t you use your code in combination with ini_set('session.gc-maxlifetime', 1800)? Otherwise your session information could get destroyed while your session is still supposed to be valid, at least if the ini setting is the standard 24 minutes. Or am I missing something?

    – jeroen

    Oct 27, 2010 at 21:05

  • 11

    @jeron: Yes, you should. But note that session.gc_maxlifetime depends on the file’s last modification date if the session save handler files is used. So session.gc_maxlifetime should be at least equal to the life time of this custom expiration handler.

    – Gumbo

    Oct 27, 2010 at 21:13

153

Simple way of PHP session expiry in 30 minutes.

Note : if you want to change the time, just change the 30 with your desired time and do not change * 60: this will gives the minutes.


In minutes : (30 * 60)
In days : (n * 24 * 60 * 60 ) n = no of days


Login.php

<?php
    session_start();
?>

<html>
    <form name="form1" method="post">
        <table>
            <tr>
                <td>Username</td>
                <td><input type="text" name="text"></td>
            </tr>
            <tr>
                <td>Password</td>
                <td><input type="password" name="pwd"></td>
            </tr>
            <tr>
                <td><input type="submit" value="SignIn" name="submit"></td>
            </tr>
        </table>
    </form>
</html>

<?php
    if (isset($_POST['submit'])) {
        $v1 = "FirstUser";
        $v2 = "MyPassword";
        $v3 = $_POST['text'];
        $v4 = $_POST['pwd'];
        if ($v1 == $v3 && $v2 == $v4) {
            $_SESSION['luser'] = $v1;
            $_SESSION['start'] = time(); // Taking now logged in time.
            // Ending a session in 30 minutes from the starting time.
            $_SESSION['expire'] = $_SESSION['start'] + (30 * 60);
            header('Location: http://localhost/somefolder/homepage.php');
        } else {
            echo "Please enter the username or password again!";
        }
    }
?>

HomePage.php

<?php
    session_start();

    if (!isset($_SESSION['luser'])) {
        echo "Please Login again";
        echo "<a href="http://localhost/somefolder/login.php">Click Here to Login</a>";
    }
    else {
        $now = time(); // Checking the time now when home page starts.

        if ($now > $_SESSION['expire']) {
            session_destroy();
            echo "Your session has expired! <a href="http://localhost/somefolder/login.php">Login here</a>";
        }
        else { //Starting this else one [else1]
?>
            <!-- From here all HTML coding can be done -->
            <html>
                Welcome
                <?php
                    echo $_SESSION['luser'];
                    echo "<a href="http://localhost/somefolder/logout.php">Log out</a>";
                ?>
            </html>
<?php
        }
    }
?>

LogOut.php

<?php
    session_start();
    session_destroy();
    header('Location: http://localhost/somefolder/login.php');
?>

9

  • 44

    Combining logic and presentation is ill-advised in this day and age when MVC is the norm.

    – bcosca

    May 9, 2012 at 16:54


  • 33

    @stillstanding Speak for yourself [smile] I view MVC as an abomination.

    – user336063

    Aug 20, 2014 at 22:39

  • 5

    Is MVC a good idea even when the project is small, with a single programmer? I feel like I should be making my own projects in the MVC model (or solve the problem THEN make it MVC) but with a lack of experience with MVC it just becomes a mental block “How do I make this MVC?” and a distraction from the initial goal/problem requiring a solution.

    – MrVimes

    Jul 27, 2018 at 9:36

  • 3

    @bcosca Not at all. Mixing logic with markup is essentially legitimate pattern in PHP. Moreover, that has been the whole point of PHP form the very beginning. And if you look at the most popular frontend framework now days: ReactJS, you will see it does the same.

    – C-F

    Oct 22, 2019 at 7:59

  • 11

    @bsosca as many here should, you should spend more time worrying about solutions to the problems and allowing the OP to figure that out than hijacking a question to make some point you think is valid 😉

    – Mattt

    Oct 23, 2019 at 19:27

47

Is this to log the user out after a set time? Setting the session creation time (or an expiry time) when it is registered, and then checking that on each page load could handle that.

E.g.:

$_SESSION['example'] = array('foo' => 'bar', 'registered' => time());

// later

if ((time() - $_SESSION['example']['registered']) > (60 * 30)) {
    unset($_SESSION['example']);
}

Edit: I’ve got a feeling you mean something else though.

You can scrap sessions after a certain lifespan by using the session.gc_maxlifetime ini setting:

Edit:
ini_set(‘session.gc_maxlifetime’, 60*30);

2

  • 1

    session.gc-maxlifetime is probably the best way to go.

    – Powerlord

    Feb 6, 2009 at 13:45

  • 3

    There are some issues with the session cookie lifetime, most notably, it relies on the client to enforce it. The cookie lifetime is there to allow the client to clean up useless/expired cookies, it is not to be confused with anything security related.

    – Jacco

    May 15, 2012 at 12:32