Eliminate unnecessary session writes for guest users#5541
Open
Deltik wants to merge 7 commits intoe107inc:masterfrom
Open
Eliminate unnecessary session writes for guest users#5541Deltik wants to merge 7 commits intoe107inc:masterfrom
Deltik wants to merge 7 commits intoe107inc:masterfrom
Conversation
BREAKING CHANGE: The `secure_image::$random_number` property is now private and contains JWT tokens instead of session IDs. Legacy code accessing this property will continue to work via magic methods, but direct manipulation may cause undefined behavior. This change eliminates the need for database sessions when generating CAPTCHAs for anonymous users, solving the rapidly growing session table issue where bot traffic was creating thousands of orphaned sessions. Key changes: - Add JWT handler (`e_jwt`) for stateless CAPTCHA token generation - Implement lazy loading with magic methods for backward compatibility - Store CAPTCHA solutions in self-contained encrypted JWT tokens - Add configurable TTL (default 10 min) and optional IP verification - Remove dependency on database sessions for anonymous CAPTCHA users - Add test coverage for backwards compatibility The session table growth should be enormously reduced for sites with bot traffic and other one-time visitors that don't otherwise make use of sessions. Fixes: e107inc#5262
This change prevents the message handler from writing to the session storage when there are no messages to store, reducing unnecessary database writes for guest users. This fix: - Adds an `eMessage::isSessionDataEmpty()` helper to check if message arrays are empty - Introduces an `eMessage::setSessionData()` wrapper that only writes non-empty data - Clears the session key when all message arrays are empty - Adds an `eMessage::getSessionData()` wrapper to ensure the proper array structure when cleared or partially populated This eliminates the `_system_messages` key session write for visitors who have no pending messages to display on the next page, reducing the session storage overhead. Supports: e107inc#5262
Implement a hybrid CSRF token system that eliminates session writes for anonymous visitors while maintaining backward compatibility for authenticated users. - Add new CSRF handler classes with strategy pattern - `CSRFTokenHandler`: Abstract base class - `CSRFSessionHandler`: Session-based tokens for authenticated users - `CSRFCookieHandler`: JWT + double-submit cookie for guests - Refactor `e_session` to use CSRF handlers via `getCSRFHandler()` - Use `$_SESSION[e_COOKIE]` to deduce auth status before USERID is defined - Automatically clean up guest CSRF cookie on authentication - Reuse existing session validation logic for request fingerprinting - Maintain full backward compatibility with `e_TOKEN` constant The cookie-based handler uses JWT tokens with the same TTL as the session's and validates using the double-submit cookie pattern. Request fingerprinting includes IP address and user agent validation based on security level. This change significantly reduces session storage overhead for sites with high guest traffic by eliminating the `__form_token` session write for anonymous visitors. Supports: e107inc#5262
CHAP authentication is largely obsolete and unnecessary for most sites. When the `password_CHAP` preference is disabled (which is the default), skip generating `challenge`, `prevchallenge`, and `prevprevchallenge` session values. This reduces unnecessary session writes for guest users, helping address issue e107inc#5262 where sessions were being created for anonymous visitors. In the unlikely case that sites that have `password_CHAP` disabled but rely on the challenge session values being present, admins will need to enable `password_CHAP` in their core preferences. This change also removes the unused "ubrowser" session key that was bundled in the CHAP challenge code generator. Supports: e107inc#5262
When guests visit the site without performing any actions that require session state, avoid creating persistent session storage. This optimization: - Skips session validation data storage for guests (no `_session_validate_data`) - Skips cookie validation timer for guests (no `_cookie_session_validate`) - Destroys empty sessions during shutdown to prevent disk writes Supports: e107inc#5262
cc949b2 to
dec1316
Compare
CaMer0n
reviewed
Sep 16, 2025
Member
There was a problem hiding this comment.
Great work Nick! What do you think about renaming this file to e_jwt_class.php ? (to match e_file, e_parse etc)
Member
Author
There was a problem hiding this comment.
The precedent looked uncertain and inconsistent to me because we also have:
e_bbcodeinbbcode_handler.phpe_forminform_handler.phpe_jshelperinjs_helper.phpe_mediainmedia_class.phpe_menuinmenu_class.phpe_modelinmodel_class.phpe_onlineinonline_class.php
So I felt my way through the name jwt_handler.php. But you're the boss, so if you'd change the name jwt_handler.php → e_jwt_class.php, we can do that!
Member
There was a problem hiding this comment.
You're right. We're kind of stuck with those old files. If you don't mind changing it to e_jwt_class that would be great. I believe PHPStorm is happier when there's a file-name/class-name match too.
Update MySQL and Xdebug sources for unit tests
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation and Context
This change solves the rapidly growing session table issue where bot traffic and anonymous visitors were creating thousands of orphaned database sessions, causing the
e107_sessiontable to balloon from a reported 6 rows to 17,334+ rows within a week, with the vast majority being guest sessions (session_user = 0).Fixes: #5262
Description
This PR comprehensively eliminates unnecessary session writes for guest/unauthenticated users through multiple optimizations:
Key Changes
password_CHAPis disabledlanguage-listsession keyImplementation Details
e_jwthandler for stateless token generationBreaking Changes
secure_image::$random_numberis now private (access is possible using__get()and__set()magic methods but discouraged by deprecation)The session table growth should be dramatically reduced for sites with bot traffic and other one-time visitors. Only authenticated users and guests actively interacting with forms will trigger session creation.
How Has This Been Tested?
Automated
New automated tests in
secure_imageTestate107_tests/tests/unit/secure_imageTest.phpManual
eMessageusages, logging in, logging out, and clicking aroundTypes of Changes
Checklist