Sesshin
Object-oriented, extendable advanced session handling component written with
security in mind that mitigates attacks like Session Hijacking, Session Fixation,
Session Exposure, Sesion Poisoning, Session Prediction., (*1)
Awarded 1st place in
php.pl contest., (*2)
Features:, (*3)
- smart session expiry control
- prevents session adoption, i.e. session ids generated only by the component
are acceptable (strict model)
- sends cookie only when session really created
- session id rotation (anti session hijacking), based on time and/or number of
requests
- configurable:
- unlike PHP native mechanism, you don't have to use cron or resource-consuming
100% garbage collecting probability to ensure sessions are removed exactly
after specified time
- convention over configuration - possible to configure user-defined stores, listeners (observers),
entropy callback and fingerprint generators, but all of them have defaults set out-of-the-box
- 100% independent from insecure native PHP session extension
, (*4)
Usage
Installation
composer require sobstel/sesshin
Create new session
Only when create()
called, session cookie is created (for native PHP session
handler cookie is present all the time whether it's needed or not)., (*5)
$session->create();
Open existing session
If session was not created earlier, session is not opened and false
is returned., (*6)
$session->open();
If you want to create new session if it does not exist already, just pass true
as argument. It will call create()
transparently., (*7)
$session->open(true);
Regenerate session id
// auto-regenerate after specified time (secs)
$session->setIdTtl(300);
// auto-regenerate after specified number of requests
$session->setIdRequestsLimit(10);
// manually
$session->regenerateId();
Listen to special events
use Sesshin\Event\Event;
$eventEmitter = $session->geEmitter();
$eventEmitter->addListener('sesshin.no_data_or_expired', function(Event $event) {
die('Session expired or session adoption attack!');
});
$eventEmitter->addListener('sesshin.expired', function(Event $event) {
die(sprintf('Session %s expired!', $event->getSession()->getId()));
});
$eventEmitter->addListener('sesshin.invalid_fingerprint', function(Event $event) {
die('Invalid fingerprint, possible attack!');
});
User session
use Sesshin\User\Session as UserSession;
use Sesshin\Store\FileStore;
$userSession = new UserSession(new FileStore('/path/to/dir'));
$userSession->create();
$userSession->login(123);
if ($userSession->isLogged()) {
echo sprintf('User %s is logged', $userSession->getUserId());
// Or if you have some kind of UserRepository class, which can be used to fetch user data
$user = UserRepository::find($userSession->getUserId());
echo sprintf('User %s is logged', $user->getUsername());
}
Store
Sesshin provides default FileStore., (*8)
use Sesshin\Session;
use Sesshin\Store\FileStore;
$session = new Session(new FileStore('/path/to/dir'));
Note! Using /tmp as a directory is not secure on shared hosting., (*9)
Alternatively you can use one of numerous
doctrine/cache
providers., (*10)
use Sesshin\Store\DoctrineCache;
use Doctrine\Common\Cache\MemcachedCache;
$memcached = new Memcached;
// here configure memcached (add servers etc)
$session = new Session(new DoctrineCache(new MemcachedCache($memcached)));
You can also implement your own store using Sesshin\Store\StoreInterface
., (*11)
Change entropy algorithm
Entropy is used to generate session id., (*12)
$session->getIdHandler()->setEntropyGenerator(new MyFancyEntropyGenerator());
MyFancyEntropyGenerator
must implement Sesshin\EntropyGenerator\EntropyGeneratorInterface
., (*13)
Change session ID store
By default session ID is stored in cookie, but sometimes you may need to force
session id, eg. based on some token, query string var, etc., (*14)
$session->getIdHandler()->setIdStore(new MyFancyIdStore());
MyFancyIdStore
must implement Sesshin\Id\Store\StoreInterface
., (*15)