monkeyscloud / monkeyslegion-session
Installs: 0
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/monkeyscloud/monkeyslegion-session
Requires
- php: ^8.4
- monkeyscloud/monkeyslegion-core: ^1.0
- monkeyscloud/monkeyslegion-database: ^1.0
- monkeyscloud/monkeyslegion-query: ^1.0
- psr/http-message: ^2.0
- psr/http-server-handler: ^1.0
- psr/http-server-middleware: ^1.0
Requires (Dev)
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^13.1@dev
This package is auto-updated.
Last update: 2026-02-15 13:22:45 UTC
README
1. Session Composition (The Core)
A session instance in MonkeysLegion will consist of the following data points:
| Component | Description | Example / Value |
|---|---|---|
| Session ID | Unique, cryptographically secure identifier. | ml_sess_8f2d9c1a... |
| Payload | Persistent data stored for the user. | {"user_id": 42, "role": "admin"} |
| Flash Data | Temporary data that is deleted after the next request. | {"status": "Profile updated!"} |
| Created At | Timestamp of when the session was first generated. | 1707782400 (Unix) |
| Last Activity | Timestamp updated on every request (for idle timeout). | 1707782900 (Unix) |
| Expiration | Hard cutoff time when the session becomes invalid. | 1707786000 (Unix) |
2. Security Fingerprinting (Validation)
To prevent session hijacking, we store and verify these browser/network traits:
- User-Agent (UA): The browser string. If it changes mid-session, we immediately kill the session (High-risk indicator).
- IP Address: The user's network address.
- Strict Mode: Invalidate session if IP changes.
- Relaxed Mode: Ignore (better for mobile users moving between Wi-Fi and 5G).
- CSRF Token: A unique token linked to this specific Session ID to prevent Cross-Site Request Forgery.
3. Session State Lifecycle
- Generation: Create ID → Set Cookie → Initialize Storage.
- Validation: Check Cookie ID → Match with Driver → Verify IP/UA.
- Update: Refresh
Last Activity→ Write new Payload/Flash data. - Destruction: Clear Storage → Expire Cookie.
4. Architecture Overview
SessionDriverInterface
| Method | Arguments | Returns | Description |
|---|---|---|---|
| open | path, name |
bool |
Initialize the storage resource. |
| close | - | bool |
Close the storage resource. |
| read | id |
string |
Retrieve serialized session data by ID. |
| write | id, data |
bool |
Save serialized session data. |
| destroy | id |
bool |
Delete the session data from storage. |
| gc | maxLifetime |
int |
Garbage Collection: Delete sessions older than X. |
| lock | id, timeout |
bool |
Acquire an exclusive lock on the session ID. |
| unlock | id |
bool |
Release the lock so other requests can proceed. |
SessionManager Details
The SessionManager is the high-level class your application code will actually interact with. It manages the Session Object (the data) and coordinates with the Driver (the storage).
Responsibilities of the Manager
- Bootstrapping: Reading the Session ID from the request cookies and asking the Driver for the data.
- Serialization: Turning the PHP array into a string (and back) so the Driver can save it.
- Flash Management: Handling data that only lasts for one "hop" (request).
- Security Checks: Comparing the User-Agent or IP before allowing access.
SessionManager Methods
| Method | Description |
|---|---|
| start() | Resumes or starts a new session. |
| getId() / setId() | Get or manually set the Session ID. |
| get($key, $default) | Retrieve data (supports dot notation like user.id). |
| set($key, $value) | Store data in the session. |
| has($key) | Returns true if the key is present. |
| flash($key, $value) | Store data for the next request only. |
| pull($key) | Get the value and immediately delete it. |
| regenerate() | Change the Session ID (Crucial for login to prevent fixation). |
| destroy() | Wipe all data and remove the session from storage. |
5. Session Middleware: The Request Lifecycle
The Middleware bridges the HTTP Request/Response with the Session Manager. It ensures data is consistent and atomic.
| Phase | Action | Detail |
|---|---|---|
| 1. Extract | getCookie() |
Look for the session cookie (e.g., ML_SESS) in the Request. |
| 2. Start | manager->start() |
The Manager triggers driver->lock() and driver->read(). |
| 3. Inject | withAttribute() |
The Session object is attached to the Request for use in Controllers. |
| 4. Process | handler->handle() |
The actual application logic runs (Routes, Controllers, Actions). |
| 5. Capture | getResponse() |
The Middleware catches the resulting Response object. |
| 6. Commit | manager->save() |
The Manager triggers driver->write() and driver->unlock(). |
| 7. Finalize | set-cookie |
If the session is new or regenerated, add the Set-Cookie header to the Response. |
Logic Flow Diagram (Conceptual)
- Request In ↓
- SessionMiddleware::process() → [Manager] → [Driver] → (LOCK & READ) ↓
- Controller / Logic →
$request->getAttribute('session')->set('key', 'value')↓ - SessionMiddleware (Post-Process) → [Manager] → [Driver] → (WRITE & UNLOCK) ↓
- Response Out (with Set-Cookie header)
Since we are using Atomic Locking, the Middleware must be careful. If an exception occurs during the "App Phase" (Step 4), the Middleware should still trigger the Unlock mechanism in a finally block to ensure the session isn't stuck in a locked state for other requests. (probably re throw in catch if user didn't already catch that occurred exception)
6. Project Structure
Since we are aligning with the monkeyslegion- ecosystem, the architecture needs to be modular, interface-driven, and ready for PSR-11 (Dependency Injection).
monkeyslegion-session/
├── src/
│ ├── Contracts/
│ │ ├── SessionInterface.php # The Manager's API
│ │ ├── DriverInterface.php # The Storage Contract (with lock/unlock)
│ ├── Drivers/
│ │ ├── DatabaseDriver.php # PDO/DB implementation
│ │ ├── RedisDriver.php # PhpRedis/Predis implementation
│ │ └── FileDriver.php # Local filesystem implementation
│ ├── Middleware/
│ │ └── SessionMiddleware.php # PSR-15 Middleware logic
│ ├── SessionManager.php # The "Brain" (Coordinates Manager + Drivers)
│ ├── SessionBag.php # The Data container (handles Flash/Payload)
│ └── Exceptions/
│ ├── SessionException.php
│ └── SessionLockException.php # If a lock cannot be acquired (timeout)
├── tests/ # Unit and Integration tests
├── composer.json
└── README.md
Component Breakdown
1. The SessionBag
Instead of putting all logic in the Manager, a SessionBag holds the actual data array. It handles the "Dot Notation" (e.g., $session->get('user.profile.name')) and manages which keys are Flash (one-time use) vs. Persistent.
2. The SessionManager (The Orchestrator)
This class should be injected into your Middleware or Controllers.
- It uses the
DriverInterfaceto fetch data. - It uses a
Serializerto decode that data into theSessionBag. - Important: It must handle the
regenerate()method, which creates a new ID but keeps the data (crucial to prevent Session Fixation attacks during login).
3. The Driver Implementations
- Database: Needs a table with
id(string),payload(text), andlast_activity(integer/timestamp). - Redis: Should use
EXPIREto let Redis handle the "Garbage Collection" automatically. - File: Needs
flock()to handle the Atomic Locking.
Roadmap
Phase 1: Core Foundation
- Implement
SessionInterfacecontract - Implement
DriverInterfacecontract - Create
SessionBagwith dot notation support - Create
SessionManagerorchestrator - Add basic exception handling
Phase 2: Driver Implementations
- Implement
FileDriverwithflock()support - Implement
DatabaseDriverwith PDO - Implement
RedisDriverwith atomic operations - Add driver-specific tests
Phase 3: Middleware & Integration
- Implement PSR-15
SessionMiddleware - Add atomic locking with
finallyblock - Cookie management (secure, httpOnly, sameSite)
Phase 4: Security Features
- User-Agent validation
- IP address validation (strict/relaxed modes)
- CSRF token generation and validation
- Session fixation prevention
Phase 5: Advanced Features
- Flash data management
- Garbage collection automation
- Session encryption option
- PSR-11 container integration
Phase 6: Documentation & Release
- Complete API documentation
- Usage examples and tutorials
- Performance benchmarks
- v1.0.0 stable release
Contributing
Welcome to contribute!
This is an open-source project and we appreciate any help from the community. Whether it's a bug fix, new feature, or documentation improvement, all contributions are valued.
How to Contribute
- Fork the repository
- Clone your fork locally
- Create a new branch for your feature/fix (
git checkout -b feature/amazing-feature) - Make your changes
- Test your changes thoroughly
- Commit your changes (
git commit -m 'Add amazing feature') - Push the branch to your fork
- Submit a Pull Request
Guidelines
- Follow PSR-12 coding standards
- Write unit tests for new features (Or it gonna need to be tested by us before merge)
- Update documentation as needed
- Keep commits atomic and well-described
- Be respectful and constructive in discussions
We look forward to your contributions!