Store PHP sessions in the database

This commit is contained in:
Frédéric Guillot
2017-12-06 16:19:11 -08:00
committed by Frédéric Guillot
parent 421531bd4f
commit ccd177ada6
58 changed files with 405 additions and 382 deletions

View File

@@ -7,7 +7,7 @@ use Kanboard\Core\Base;
/**
* Session Flash Message
*
* @package session
* @package Kanboard\Core\Session
* @author Frederic Guillot
*/
class FlashMessage extends Base
@@ -43,11 +43,11 @@ class FlashMessage extends Base
*/
public function setMessage($key, $message)
{
if (! isset($this->sessionStorage->flash)) {
$this->sessionStorage->flash = array();
if (! session_exists('flash')) {
session_set('flash', []);
}
$this->sessionStorage->flash[$key] = $message;
session_merge('flash', [$key => $message]);
}
/**
@@ -61,9 +61,14 @@ class FlashMessage extends Base
{
$message = '';
if (isset($this->sessionStorage->flash[$key])) {
$message = $this->sessionStorage->flash[$key];
unset($this->sessionStorage->flash[$key]);
if (session_exists('flash')) {
$messages = session_get('flash');
if (isset($messages[$key])) {
$message = $messages[$key];
unset($messages[$key]);
session_set('flash', $messages);
}
}
return $message;

View File

@@ -0,0 +1,70 @@
<?php
namespace Kanboard\Core\Session;
use PicoDb\Database;
use SessionHandlerInterface;
/**
* Class SessionHandler
*
* @package Kanboard\Core\Session
*/
class SessionHandler implements SessionHandlerInterface
{
const TABLE = 'sessions';
/**
* @var Database
*/
private $db;
public function __construct(Database $db)
{
$this->db = $db;
}
public function close()
{
return true;
}
public function destroy($sessionID)
{
return $this->db->table(self::TABLE)->eq('id', $sessionID)->remove();
}
public function gc($maxlifetime)
{
return $this->db->table(self::TABLE)->lt('expire_at', time())->remove();
}
public function open($savePath, $name)
{
return true;
}
public function read($sessionID)
{
$result = $this->db->table(self::TABLE)->eq('id', $sessionID)->findOneColumn('data');
return $result ?: '';
}
public function write($sessionID, $data)
{
$lifetime = time() + (ini_get('session.gc_maxlifetime') ?: 1440);
if ($this->db->table(self::TABLE)->eq('id', $sessionID)->exists()) {
return $this->db->table(self::TABLE)->eq('id', $sessionID)->update(array(
'expire_at' => $lifetime,
'data' => $data,
));
}
return $this->db->table(self::TABLE)->insert(array(
'id' => $sessionID,
'expire_at' => $lifetime,
'data' => $data,
));
}
}

View File

@@ -7,7 +7,7 @@ use Kanboard\Core\Base;
/**
* Session Manager
*
* @package session
* @package Kanboard\Core\Session
* @author Frederic Guillot
*/
class SessionManager extends Base
@@ -38,6 +38,8 @@ class SessionManager extends Base
*/
public function open()
{
session_set_save_handler(new SessionHandler($this->db), true);
$this->configure();
if (ini_get('session.auto_start') == 1) {
@@ -46,8 +48,6 @@ class SessionManager extends Base
session_name('KB_SID');
session_start();
$this->sessionStorage->setStorage($_SESSION);
}
/**

View File

@@ -1,92 +0,0 @@
<?php
namespace Kanboard\Core\Session;
/**
* Session Storage
*
* @package session
* @author Frederic Guillot
*
* @property array $user
* @property array $flash
* @property array $csrf
* @property array $postAuthenticationValidated
* @property array $filters
* @property string $redirectAfterLogin
* @property string $captcha
* @property string $commentSorting
* @property bool $hasSubtaskInProgress
* @property bool $hasRememberMe
* @property bool $subtaskListToggle
* @property string $scope
* @property bool $twoFactorBeforeCodeCalled
* @property string $twoFactorSecret
* @property string $oauthState
* @property int $smsTwoFactorSecret
*/
class SessionStorage
{
/**
* Pointer to external storage
*
* @access private
* @var array
*/
private $storage = array();
/**
* Set external storage
*
* @access public
* @param array $storage External session storage (example: $_SESSION)
*/
public function setStorage(array &$storage)
{
$this->storage =& $storage;
// Load dynamically existing session variables into object properties
foreach ($storage as $key => $value) {
$this->$key = $value;
}
}
/**
* Get all session variables
*
* @access public
* @return array
*/
public function getAll()
{
$session = get_object_vars($this);
unset($session['storage']);
return $session;
}
/**
* Flush session data
*
* @access public
*/
public function flush()
{
$session = get_object_vars($this);
unset($session['storage']);
foreach (array_keys($session) as $property) {
unset($this->$property);
}
}
/**
* Copy class properties to external storage
*
* @access public
*/
public function __destruct()
{
$this->storage = $this->getAll();
}
}