seba1rx/sessionadmin
最新稳定版本:v2.2
Composer 安装命令:
composer require seba1rx/sessionadmin
包简介
PHP session management with security hardening, hijacking detection, and URL authorization for MPA and SPA applications
README 文档
README
PHP session management library with security hardening and URL authorization.
composer require seba1rx/sessionadmin
Features
Session security
- Named sessions with configurable cookie parameters
- Hijacking detection: IP prefix + User-Agent fingerprint verified on every request
- Proxy-aware IP detection (reads
X-Forwarded-Forand equivalent headers) - Session destruction when a request arrives after the configured lifetime
- Session ID regenerated on login and randomly (~3% of requests) to resist fixation
URL authorization (MPA)
- Define an
$allowedUrlslist; guests are redirected toindex.phpon any unlisted page - Expandable per user role or profile
- Disable entirely for SPA apps (
$appIsSpa = true, the default)
Quick start
SessionAdmin is abstract with no abstract methods. Extend it and define a constructor:
// App/MySession.php namespace App; use Seba1rx\SessionAdmin\SessionAdmin; class MySession extends SessionAdmin { public function __construct() { $this->sessionName = 'my_app'; $this->sessionLifetime = 3600; // seconds $this->keys = ['theme' => 'light']; // pre-seeded session keys } }
Then on every entry point, before any output:
require 'vendor/autoload.php'; $session = new App\MySession(); $session->useAuthorization = false; // true for MPA URL enforcement $session->activateSession(); // replaces session_start() // On login: $session->createUserSession($userId); // On logout: $session->terminate(); // Auth check: if (!empty($_SESSION['sessionadmin']['isUser'])) { // authenticated }
Public API
| Method | Description |
|---|---|
activateSession() |
Starts or resumes the session; runs all security checks |
createUserSession(mixed $id) |
Marks session as authenticated, regenerates session ID |
terminate() |
Destroys session, reinitialises as guest, redirects to index.php (MPA) |
setSessionHandler(\SessionHandlerInterface $handler) |
Plug in a custom storage backend; call before activateSession() |
setTabHandler(TabHandlerInterface $handler) |
Inject a tab handler (e.g. seba1rx/tabmanager); call before activateSession() |
The full class is documented via docblocks — your IDE will surface every property and its purpose.
Session data written to $_SESSION['sessionadmin']
| Key | Present | Description |
|---|---|---|
appType |
Always | 'SPA' or 'MPA' — reflects the $appIsSpa flag |
isUser |
Always | true when authenticated, false for guests |
id_user |
After login | Value passed to createUserSession() |
msg |
Always | Human-readable state label |
uniqueId |
Always | 12-char hex token, stable for the session lifetime |
ipPrefix |
Always | First N octets of the client IP (hijacking detection) |
userAgent |
Always | User-Agent string (hijacking detection) |
time_atRequest |
Always | Unix timestamp of the last request |
time_sinceLastRequest |
Always | Seconds elapsed since the previous request |
allowedUrl |
MPA only | Copy of $allowedUrls used for URL authorization |
urlIsAllowedToLoad |
MPA only | true when the current URL is in the allow-list |
allowedUrl and urlIsAllowedToLoad are omitted entirely in SPA mode — they only make sense when URL authorization is active.
Custom session storage
By default the package uses PHP's native file-based session storage. Pass any SessionHandlerInterface implementation to setSessionHandler() before calling activateSession() to swap the backend:
$session = new App\MySession(); $session->setSessionHandler(new RedisSessionHandler($redis)); $session->activateSession();
Any PSR-compatible or custom handler works — Redis, database, encrypted file store, etc. The handler must be set before activateSession() because PHP applies the handler prior to calling session_start().
Tab isolation (optional)
Per-browser-tab session isolation is provided by the companion package seba1rx/tabmanager, which implements TabHandlerInterface.
composer require seba1rx/tabmanager
Inject it before calling activateSession() using SessionAdminBridge — the integration class shipped with tabmanager:
use Seba1rx\TabManager\Bridge\SessionAdminBridge; $session = new App\MySession(); $session->setTabHandler(new SessionAdminBridge()); $session->autoCleanupTabs = 30; // optional: remove tabs inactive for > 30 s $session->activateSession(); // After the JS client has registered the tab: $session->tabHandler->set('cart', ['apple' => 3]); $cart = $session->tabHandler->get('cart'); $ready = $session->tabHandler->isTabIndexed(); // false until JS registers the tab
SessionAdminBridge extends TabManager but does not call session_start() in its constructor — activateSession() owns the session lifecycle and configures the session name and cookie parameters before the session starts. Both packages write to distinct keys in $_SESSION (sessionadmin vs tabmanager) and do not interfere with each other.
Tab session loss (autoCleanupTabs + tabmanager:session-lost)
When $autoCleanupTabs is set, SessionAdmin prunes inactive tabs on every activateSession() call. If the browser suspends a tab (Chrome Memory Saver, OS memory pressure), the JS heartbeat pauses — and the tab may be pruned while invisible. When the user returns, tabmanager's JS client checks /tabmanager/tab-status. If the tab is no longer indexed, it fires a tabmanager:session-lost event on document and stops the heartbeat. Listen for this event to show a warning or prompt the user to reload:
document.addEventListener('tabmanager:session-lost', () => { // Tab data was pruned by autoCleanupTabs while the tab was suspended. // Show a warning and let the user decide whether to reload. showSessionLostBanner(); });
The event carries event.detail.tabId with the UUID of the lost tab.
Contracts (interfaces)
The package ships two interfaces under Seba1rx\SessionAdmin\Contracts:
| Interface | Role | Key methods |
|---|---|---|
SessionInterface |
Implemented by SessionAdmin |
activateSession(), createUserSession(), terminate() |
TabHandlerInterface |
Implemented by seba1rx/tabmanager |
set(), get(), isTabIndexed(), cleanupInactiveTabs(), … |
TabHandlerInterface defines the full tab lifecycle contract. Any class implementing it can be injected via setTabHandler() — SessionAdmin never depends on the concrete TabManager class.
Example — mock session in tests:
$mockSession = $this->createMock(SessionInterface::class); $mockSession->expects($this->once())->method('activateSession');
Example — mock tab handler in tests:
$mockTabs = $this->createMock(TabHandlerInterface::class); $mockTabs->method('get')->with('cart')->willReturn(['apple' => 3]); $session->setTabHandler($mockTabs);
Demos
| Demo | Description |
|---|---|
demo/basic/ |
Minimal login/logout — the simplest possible implementation |
demo/mpa/ |
Multi-page app with URL authorization and $allowedUrls |
demo/spa/ |
Single-page app, SPA mode, AJAX login |
demo/tabmanager/ |
SessionAdmin + TabManager integration — shared session, per-tab data isolation |
Each demo is self-contained with its own composer.json.
Running a demo locally
- Install dependencies for the chosen demo:
cd demo/basic
composer install
- Start PHP's built-in web server from the demo directory:
php -S localhost:8000
- Open your browser and navigate to:
http://localhost:8000
The built-in server serves
index.phpby default. Change the port if8000is already in use (php -S localhost:8080).
统计信息
- 总下载量: 61
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 2
- 点击次数: 1
- 依赖项目数: 0
- 推荐数: 1
其他信息
- 授权协议: MIT
- 更新时间: 2020-10-21