Session management in PHP

Sessions in PHP: How they work and what governs them

PHP sessions are governed by several parameters that can either work together smoothly or conflict with each other.

All the PHP settings listed below can be configured in php.ini, in the vhost (if using Apache's modPHP), or in a .htaccess file (if .htaccess usage is allowed).

General explanation

When we load a PHP-based website in a browser, the site's default mechanism is to start a session, which is a small storage space for information about us that can be reused on subsequent pages — allowing the server to "remember" us. Thanks to this, for instance, the next page won’t need to ask for our username and password again.

On the server side, these values are stored (usually in an individual file for each user session). In order for the server to recognize the browser that previously visited a page, it stores a session ID in the browser using the well-known cookie mechanism.

A cookie is also a way of storing information in the browser, but for security (and data privacy), we usually only store brief and non-personal data there, such as... a session ID.

This cookie is reused for every request to the same site (same URL): the browser automatically sends the cookie whenever the user visits any other page on the site. The server then automatically reads this cookie — which has a name matching the session cookie name — finds the corresponding file on disk, and loads it into memory before proceeding with PHP code execution.

Note that this mechanism is not unique to PHP, but each programming language has to manage it in its own way.

In PHP, the way sessions are managed can be adjusted through server configuration options. For example, sessions can be stored on a Redis server (commonly used when multiple web servers serve the same site, and you want users to have a seamless experience regardless of which server processes their request).

By default, PHP stores these sessions in a folder (often /var/lib/php/sessions on Linux) and gives them a lifespan of 24 minutes (or 1440 seconds, since parameters are stored in seconds).

Every time this session is used (e.g., each page loaded), the timer is reset to extend the session for another 24 minutes.

On the client side, if there is no activity (e.g., page load) for 24 minutes, the cookie (initially marked with a 24-minute lifespan) becomes invalid, and the browser stops sending it to the server on new requests — we then say that the session has expired. The site will probably ask the user to log in again.

On the server side, the behavior is somewhat similar and serves as a precaution: the server considers all session files that have not been "touched" (accessed or modified) in the last 24 minutes as expired.
However — and this is very important to understand the whole mechanism — these corresponding files are not automatically deleted after 24 minutes. Whether they are deleted or not depends on the site's traffic and the probability that a mechanism called the garbage collector (gc) is triggered.
This garbage collector is a process that may or may not be launched on each new site visit. The parameters below govern this mechanism.

On the server side

session.gc_probability

This PHP configuration parameter specifies the probability (expressed as a percentage and in conjunction with session.gc_divisor, see below) that the garbage collector (gc) routine will be triggered at each request. The default value is 1. The value must be 0 or greater.

session.gc_divisor

This parameter works together with session.gc_probability to define the probability that the gc routine will run when a session starts.
The probability is calculated as gc_probability/gc_divisor. For example, 1/100 means there is a 1% chance that the gc routine will run at each request. The default value is 100.

session.gc_maxlifetime

This PHP setting defines the lifetime of session data on the server, in seconds. After this time, data is considered obsolete and may be deleted (if the garbage collector runs).
Sessions can thus become obsolete when they start (depending on gc_probability and gc_divisor).
The default value is 1440 seconds (24 minutes). ⚠️ Be careful: if several scripts set different gc_maxlifetime values for the same user session, the smallest value will prevail.

session.save_path

This parameter defines where session files are stored on the server.
Note: If you use it with its optional sub-directory count (e.g., "2;/tmp"), the default garbage collector will no longer run, so all the explanations above about gc won’t apply anymore.

On the client side

session.cookie_lifetime

This PHP setting defines the expiration time of the cookie identifying the PHP session (see "General Explanation" above).
If set to 0, the cookie will expire when the browser window or tab is closed.

Common sense rule

As you may have understood, ideally, session.cookie_lifetime and session.gc_maxlifetime should have the same value, or gc_maxlifetime could be set to a specific value if session.cookie_lifetime is set to 0 (because, in that case, the browser/tab closure will expire the cookie, but you may still want an additional security measure on the server side in case a user leaves a tab open for a year).

The dark side of cookies

While this mechanism has worked well for decades, there are still important considerations about its reliance on cookies:

  1. Cookies are stored on the client side and are easily modifiable. They are therefore not entirely reliable, and session IDs must be hard to guess (hence, usually long, random-looking strings).
  2. These cookies can be read and modified by JavaScript running on the page, whether from the site itself, from browser extensions, or from a hack aiming to run rogue code on a trusted site (XSS or CSRF attacks).
    Some websites implement integrity-check mechanisms to validate cookie data and prevent unwanted client-side modifications.
  3. Cookies are sent with every request (actually twice: once when sending the request and once when receiving the response). Therefore, to avoid session hijacking, it's essential to secure communication channels with proper HTTPS encryption. ⚠️ Note: Many older HTTPS algorithms are now considered insecure, so you must update them regularly.
  4. Since cookies are sent with every request, avoid using them to store large amounts of data that could instead be kept on the server. This helps avoid unnecessary data transfer, which could slow down the site.

Commercial note

Although we specialize in free and open-source e-learning solutions, we are first and foremost experts in web technologies.
If you face complex technical issues, BeezNest can provide high-level expertise to solve your technical problems, whether related to security or site performance optimization.
Feel free to contact us through our online form for more information.

Let me know if you want me to format this for direct publication (with Markdown, HTML, etc.)!