Download the PHP package jeph/mysql-session without Composer
On this page you can find all versions of the php package jeph/mysql-session. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Informations about the package mysql-session
JEPH\MySQL\Session
Just Enough PHP to provide MySQL session storage.
A custom PHP session handler that stores session data in a MySQL database with proper session locking.
Usage
Configuration Options
All options are passed to the create() factory method, which returns Session|false:
The factory method returns false if table names contain invalid characters (only alphanumeric and underscores are allowed) to prevent SQL injection.
| Option | Default | Description |
|---|---|---|
| table_name | sessions |
Name of the sessions table |
| lock_table_name | session_locks |
Name of the locks table |
| lock_timeout | 10 |
Seconds to wait when acquiring a lock |
| lock_max_age | 30 |
Seconds before a lock is considered abandoned |
| lock_retry_interval | 100 |
Milliseconds between lock acquisition attempts |
| security_code | '' |
Secret string for session fingerprint validation |
| lock_to_user_agent | false |
Bind session to the client's User-Agent header |
| lock_to_ip | false |
Bind session to client IP address (bool or callable) |
| read_only | false |
Open session in read-only mode (no locks, no writes) |
Database Tables
session_locks
Used for table-based session locking to ensure data consistency during concurrent requests.
| Column | Type | Description |
|---|---|---|
| session_id | VARCHAR(128) | The PHP session ID (primary key) |
| lock_token | VARCHAR(64) | Unique token identifying the lock holder |
| locked_at | INT UNSIGNED | Unix timestamp when lock was acquired |
sessions
Stores the actual session data.
| Column | Type | Description |
|---|---|---|
| session_id | VARCHAR(128) | The PHP session ID (primary key) |
| data | MEDIUMTEXT | Serialized session data (up to 16MB) |
| fingerprint | VARCHAR(64) | SHA256 hash for session hijacking protection |
| last_accessed | INT UNSIGNED | Unix timestamp for garbage collection |
Session Hijacking Protection
This handler provides optional session hijacking protection through fingerprint validation. When enabled, a hash of client characteristics is stored with the session and validated on each read. If the fingerprint doesn't match, the session is destroyed.
Configuration
Enable protection by setting one or more of these options:
Options Explained
security_code - A secret string (recommended: 12+ characters with mixed case and numbers) that is included in the fingerprint calculation. This adds server-side entropy that an attacker cannot know, making it harder to forge a valid fingerprint.
lock_to_user_agent - When true, the session is bound to the client's User-Agent header. If the User-Agent changes, the session is invalidated. Note: Some browsers (especially older IE versions) may change User-Agent between requests, so test thoroughly.
lock_to_ip - When true, the session is bound to $_SERVER['REMOTE_ADDR']. This provides strong protection but may cause issues for users whose IP changes frequently (mobile networks, some ISPs).
Using a Callable for IP Address
If your application is behind a load balancer or reverse proxy, REMOTE_ADDR will be the proxy's IP. Use a callable to extract the real client IP:
Security Considerations
- Recommended: Always set
security_codewhen using fingerprint protection - User-Agent binding adds minor security; an attacker who steals a session cookie likely has the same browser
- IP binding is stronger but may cause legitimate session loss for mobile users
- A mismatched fingerprint destroys the session and returns empty data, forcing a new session
- Uses
hash_equals()for constant-time comparison to prevent timing attacks
Upgrading Existing Sessions
If you enable fingerprint protection on an existing application, sessions created before the upgrade will be invalidated (they have no stored fingerprint). Users will need to log in again.
Session Locking
This handler implements table-based session locking to prevent race conditions during concurrent requests. When a session is read, a lock is acquired and held until the session is closed.
How it works:
- When
session_start()is called, the handler attempts to acquire a lock - If the lock is held by another request, it retries until
lock_timeoutis reached - If a lock is older than
lock_max_age, it is considered abandoned and can be claimed - The lock is released when
session_write_close()is called or the script ends
Best practices:
- Call
session_write_close()early in long-running scripts to release the lock - Keep
lock_timeoutreasonable to avoid blocking requests indefinitely - The
lock_max_ageshould be longer than your maximum expected script execution time
Long-Running Scripts
For scripts that run longer than lock_max_age, use refresh_lock() to prevent the lock from becoming stale:
The refresh_lock() method returns true if the lock was successfully refreshed, or false if no lock is held or the lock was lost. Call it at intervals shorter than lock_max_age (e.g., every lock_max_age / 2 seconds).
Read-Only Mode
Read-only mode allows you to access session data without acquiring locks and without saving any changes. This is useful for:
- High-traffic read-heavy pages where you only need to check if a user is logged in
- AJAX endpoints that read session data but don't modify it
- API endpoints where session data is needed for authentication but not modified
- Reducing lock contention when multiple requests need concurrent read access
Usage
Behavior
When read_only is true:
- No lock is acquired - Multiple read-only sessions can access the same session concurrently
- No data is written -
write()returnstruebut doesn't save changes - No timestamp updates -
updateTimestamp()returnstruebut doesn't update - Cannot create new sessions - Writing to a non-existent session ID does nothing
- Fingerprint validation still works - But mismatched fingerprints return empty data instead of destroying the session
Checking Read-Only Status
Use is_read_only() to check if the session is in read-only mode:
Use Cases
Authentication check on API endpoint:
High-traffic page with session check:
Testing
Tests are written using Pest and require a MySQL database.
Setup
-
Create a test database and user:
- Configure the database connection via environment variables (if using different credentials):
Running Tests
The test suite includes:
- session-tests.php - Basic session handler functionality (read, write, destroy, gc)
- locking-tests.php - Lock acquisition, release, stale lock handling, and concurrent access tests
- fingerprint-tests.php - Session hijacking protection via fingerprint validation
- read-only-tests.php - Read-only mode functionality and behavior
- integration-tests.php - Real PHP session integration (
session_start,read_and_close,session_regenerate_id)