PHP Session Management – Long Term Cookies for Authenticated Users

cookiesPHPsession

We want to extend the session duration for our users. I guess it doesn't matter for users who are not authenticated. We can create a PHPSESSID cookie for them and if it expires when they close their browser then fine. But for users who are authenticated we want to extend the session duration so they don't have to sign in repeatedly. We could just extend the session cookie duration for all users (authenticated, and non-authenticated) but as we handle millions of requests a month, this would mean millions of active sessions right? However, the number of users we will have to authenticate is only in the thousands. Can we change the duration of some session cookies? Is this the right approach? Or is there a better method to handle long term session cookies?

Best Answer

Are you actually using sessions to store data for non-authenticated users, or are you just calling session_start() on every page load? If that's the case, just stop initializing sessions for every visitor, and only do so when a user actually logs in.

Only start a session if one already exists:

if (session_status() === PHP_SESSION_ACTIVE) {
    session_start();
}

Start session at login:

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    if ($_POST['username'] == 'foo' && $_POST['password'] == 'bar') {
        session_start();
        $_SESSION['username'] = $_POST['username'];
    }
}

However, if you are in fact storing session data for even non-authenticated visitors, it gets a little trickier. You can't just set a custom TTL for individual sessions. You could certainly modify the session expiration length to be several days or weeks, but this would cause PHP to retain the server-side session data for the same length of time.

Your concern about millions of active sessions is understandable, but the actual impact on your server depends entirely on how you've configured PHP to handle sessions. By default, the sessions are stored on the server's file system in a temp directory. Since the session files are minuscule (assuming you aren't doing something horrific like storing BLOB data in them), you aren't likely to use a significant amount of disk space accommodating user sessions for extended lengths of time.

However, if your site experiences constant and heavy traffic, the disk IO is going to flog your server into submission. In this case, I would think about using memcache or redis as the session engine, in order to ease the load on my server's hard disk. But you don't want session data remaining in the server's physical memory for very long, so set the TTL to something relatively short like 1800 (seconds).

Now comes the tricky part: persisting long-term sessions...

When a user logs in, you can send them a custom cookie containing their session id, and with a much longer TTL (or none at all). Then, create a database entry or write a "temp" file containing the serialize()'d session, and indexed by the session id. You would need to keep this db entry or temp file in sync with the session while the user is active, but once they leave and the in-memory session expires, you still have their session data on your hard disk. When they return, days or weeks later, you can read their cookie value, retrieve the serialized session from your database or temp file, reinitialize the user's session with the original ID, and unserialize() the session data back into $_SESSION.

IMPORTANT NOTES: You would need to implement some measures to prevent session stealing, such as comparing the visitor's IP address and/or user agent (browser) against their values at login. You would also need to have some kind of cron job clear out stagnant session data from your db or temp file directory after a given length of time, otherwise it would just keep getting bigger.