Last active
October 7, 2018 23:30
-
-
Save azjezz/8a32d87df39422a12e3078a35a8c988a to your computer and use it in GitHub Desktop.
PSR-16 based session persistence for zend expressive
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/*────────────────────────────────────────────────────────────────────────────── | |
─ @author Saif Eddin Gmati <[email protected]> | |
─────────────────────────────────────────────────────────────────────────────*/ | |
declare(strict_types=1); | |
namespace Polar\Session; | |
use DateTime; | |
use Dflydev\FigCookies\FigResponseCookies; | |
use Dflydev\FigCookies\Modifier\SameSite; | |
use Dflydev\FigCookies\SetCookie; | |
use Exception; | |
use Psr\Cache\CacheItemPoolInterface; | |
use Psr\Cache\InvalidArgumentException; | |
use Psr\Http\Message\ResponseInterface; | |
use Psr\Http\Message\ServerRequestInterface; | |
use Zend\Expressive\Session\Session; | |
use Zend\Expressive\Session\SessionInterface; | |
use Zend\Expressive\Session\SessionPersistenceInterface; | |
use function bin2hex; | |
use function random_bytes; | |
class SessionPersistence implements SessionPersistenceInterface | |
{ | |
public const DEFAULT_COOKIE_OPTIONS = [ | |
'name' => 'session', | |
'secure' => false, | |
'expires' => '+30 days', | |
'path' => '/', | |
'http_only' => true, | |
]; | |
/** @var CacheItemPoolInterface $itemPool */ | |
protected $itemPool; | |
/** | |
* @var array | |
*/ | |
protected $cookieOptions; | |
/** | |
* Session constructor. | |
* | |
* @param CacheItemPoolInterface $itemPool | |
* @param array $cookieOptions | |
*/ | |
public function __construct(CacheItemPoolInterface $itemPool, array $cookieOptions = []) | |
{ | |
$this->itemPool = $itemPool; | |
$this->cookieOptions = array_merge($cookieOptions, static::DEFAULT_COOKIE_OPTIONS); | |
} | |
/** | |
* Generate a session data instance based on the request. | |
* | |
* @param ServerRequestInterface $request | |
* | |
* @return SessionInterface | |
* | |
* @throws Exception | |
* @throws InvalidArgumentException | |
*/ | |
public function initializeSessionFromRequest(ServerRequestInterface $request): SessionInterface | |
{ | |
// for some reason, $request is missing 'Cookie' header, but i was able to get the cookies via getCookieParams(); | |
// $id = FigRequestCookies::get($request,'session')->getValue() ?? $this->generateSessionId(); | |
$cookies = $request->getCookieParams(); | |
$id = $cookies['session'] ?? $this->generateSessionId(); | |
$data = $this->itemPool->getItem("session.{$id}"); | |
$data = $data->isHit() ? $data->get() : []; | |
return new Session($data, $id); | |
} | |
/** | |
* Persist the session data instance. | |
* | |
* Persists the session data, returning a response instance with any | |
* artifacts required to return to the client. | |
* | |
* @param SessionInterface $session | |
* @param ResponseInterface $response | |
* | |
* @return ResponseInterface | |
* | |
* @throws InvalidArgumentException | |
* @throws Exception | |
*/ | |
public function persistSession(SessionInterface $session, ResponseInterface $response): ResponseInterface | |
{ | |
/** @var Session $session */ | |
$id = $session->isRegenerated() ? $this->generateSessionId() : $session->getId(); | |
$this->itemPool->save( | |
$this->itemPool->getItem("session.{$id}") | |
->set($session->toArray()) | |
->expiresAfter(360000) | |
); | |
$cookieOptions = $this->getCookieOptions(); | |
$sessionCookie = SetCookie::create($cookieOptions['name']) | |
->withValue($id) | |
->withSecure($cookieOptions['secure']) | |
->withExpires(new DateTime($cookieOptions['expires'])) | |
->withPath($cookieOptions['path']) | |
->withHttpOnly($cookieOptions['http_only']); | |
if (isset($cookieOptions['same_site'])) { | |
$sessionCookie = $sessionCookie->withSameSite(SameSite::fromString($cookieOptions['same_site'])); | |
} | |
return FigResponseCookies::set( | |
$response, | |
$sessionCookie | |
); | |
} | |
/** | |
* @return array | |
*/ | |
public function getCookieOptions(): array | |
{ | |
return $this->cookieOptions; | |
} | |
/** | |
* @param array $cookieOptions | |
*/ | |
public function setCookieOptions(array $cookieOptions): void | |
{ | |
$this->cookieOptions = $cookieOptions; | |
} | |
/** | |
* Generate a session identifier. | |
* | |
* @throws Exception | |
*/ | |
private function generateSessionId(): string | |
{ | |
return bin2hex(random_bytes(16)); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment