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.
Awarded 1st place in php.pl contest.
Features:
- 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
composer require sobstel/sesshin
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).
$session->create();
If session was not created earlier, session is not opened and false
is returned.
$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.
$session->open(true);
// auto-regenerate after specified time (secs)
$session->setIdTtl(300);
// auto-regenerate after specified number of requests
$session->setIdRequestsLimit(10);
// manually
$session->regenerateId();
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!');
});
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());
}
Sesshin provides default FileStore.
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.
Alternatively you can use one of numerous doctrine/cache providers.
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
.
Entropy is used to generate session id.
$session->getIdHandler()->setEntropyGenerator(new MyFancyEntropyGenerator());
MyFancyEntropyGenerator
must implement Sesshin\EntropyGenerator\EntropyGeneratorInterface
.
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.
$session->getIdHandler()->setIdStore(new MyFancyIdStore());
MyFancyIdStore
must implement Sesshin\Id\Store\StoreInterface
.