Skip to content

sobstel/sesshin

Repository files navigation

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.

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

Build Status Scrutinizer Code Quality

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).

$session->create();

Open existing session

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);

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.

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.

Change entropy algorithm

Entropy is used to generate session id.

$session->getIdHandler()->setEntropyGenerator(new MyFancyEntropyGenerator());

MyFancyEntropyGenerator must implement Sesshin\EntropyGenerator\EntropyGeneratorInterface.

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.

$session->getIdHandler()->setIdStore(new MyFancyIdStore());

MyFancyIdStore must implement Sesshin\Id\Store\StoreInterface.