ajgl/session-concurrency-bundle
Installation:
composer require ajgl/session-concurrency-bundle
Enable the bundle in config/bundles.php:
return [
// ...
Ajgl\SessionConcurrencyBundle\AjglSessionConcurrencyBundle::class => ['all' => true],
];
Configuration:
Add to config/packages/ajgl_session_concurrency.yaml:
ajgl_session_concurrency:
max_sessions: 3 # Default max concurrent sessions
session_name: 'APP_SESSION' # Custom session name if needed
First Use Case:
config/packages/ajgl_session_concurrency.yaml: Bundle configuration.src/Resources/doc/index.md: Official documentation (check for Symfony 5+ compatibility notes).Ajgl\SessionConcurrencyBundle\DependencyInjection\Configuration.php: Defaults and validation logic.Session Validation:
Integrate the AjglSessionConcurrencyListener into Symfony’s security system. The bundle hooks into SECURITY_INTERACTIVE_LOGIN and SECURITY_AUTO_LOGIN events to validate session counts.
// Example in a custom event subscriber (if extending behavior)
public function onLogin(InteractiveLoginEvent $event) {
$session = $event->getRequest()->getSession();
$this->sessionConcurrency->validateSession($session);
}
Custom Session Storage:
For non-standard session backends (e.g., Redis, database), extend Ajgl\SessionConcurrency\SessionStorageInterface:
class CustomSessionStorage implements SessionStorageInterface {
public function countSessions(string $sessionId): int { ... }
public function invalidateSession(string $sessionId): void { ... }
}
Register it in services.yaml:
ajgl_session_concurrency.storage: '@custom_session_storage'
Whitelisting IPs/Paths: Exclude specific routes or IPs from concurrency checks via configuration:
ajgl_session_concurrency:
ignore_paths:
- '^/admin'
ignore_ips:
- '127.0.0.1'
Event-Driven Extensions:
Listen to ajgl.session_concurrency.session_invalidated to handle invalidation side effects (e.g., logging, notifications):
use Ajgl\SessionConcurrencyBundle\Event\SessionInvalidatedEvent;
public function onSessionInvalidated(SessionInvalidatedEvent $event) {
$this->logger->info('Session invalidated for user: ' . $event->getUsername());
}
firewalls and providers. No manual session handling required.$this->sessionConcurrency->validateSession($request->getSession());
Ajgl\SessionConcurrencyBundle\Tests\* for edge cases (e.g., rapid logins, session hijacking).Session Storage Assumptions:
SessionStorageInterface and ensure countSessions() accurately reflects active sessions.session.save_handler in php.ini matches your storage backend.Configuration Overrides:
security.firewalls settings. Explicitly set max_sessions and session_name in config.SECURITY_INTERACTIVE_LOGIN) may require adjustments for newer Symfony versions.Race Conditions:
Caching:
$this->sessionConcurrency->getStorage()->clearCache();
Log Invalidations:
Enable debug mode and check logs for ajgl.session_concurrency events.
monolog:
handlers:
main:
level: debug
Test with Multiple Tabs: Simulate concurrency by opening identical sessions in different browsers (e.g., Chrome + Firefox).
Check Session ID:
Verify session_id() matches your session_name config. Mismatches cause silent failures.
Custom Invalidators:
Override the default invalidation logic by extending Ajgl\SessionConcurrency\SessionConcurrency:
class CustomSessionConcurrency extends SessionConcurrency {
protected function onSessionInvalidated(string $sessionId) {
// Custom logic (e.g., send email to user)
}
}
Register as a service:
ajgl_session_concurrency.concurrency: '@custom_session_concurrency'
Dynamic Max Sessions:
Fetch max_sessions from a database or user profile:
$maxSessions = $this->userRepository->getMaxSessions($user);
$this->sessionConcurrency->setMaxSessions($maxSessions);
Grace Periods: Add a "grace period" to delay invalidation (e.g., 5 minutes):
$this->sessionConcurrency->setGracePeriod(300); // 5 minutes
How can I help you explore Laravel packages today?