I made a Session middleware class (named “Session” and mostly borrowed from the internet).
<?php
namespace Custom\Middleware;
use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;
class Session {
protected $options = array(
'name' => 'sessie',
'lifetime' => 3600,
'path' => '/',
'domain' => null,
'secure' => false,
'httponly' => true,
'cache_limiter' => 'nocache',
'autorefresh' => false
);
public function __construct(array $options = array()) {
if (is_string($options['lifetime'])) {
$options['lifetime'] = strtotime($options['lifetime']) - time();
}
$this->options = array_merge($this->options, $options);
}
public function __invoke(Request $request, Response $response, callable $next) {
$this->startSession();
return $next($request, $response);
}
protected function startSession() {
$options = $this->options;
session_set_cookie_params($options['lifetime'], $options['path'], $options['domain'], $options['secure'], $options['httponly']);
if (session_id()) {
if ($options['autorefresh'] === true && isset($_COOKIE[$options['name']]) && ini_get('session.use_cookies')) {
setcookie($options['name'], $_COOKIE[$options['name']], time() + $options['lifetime'], $options['path'], $options['domain'], $options['secure'], $options['httponly']);
}
}
session_name($options['name']);
session_cache_limiter(false);
session_start();
}
}
I also have a SessionHelper class (and file) with methods like ‘get’, ‘set’, ‘delete’ etc.
<?php
namespace Custom\Session;
class SessionHelper {
public function get($key) {
return $this->keyExists($key) ? $_SESSION[$key] : false;
}
public function set($key, $value, $overwrite = false) {
if ($this->keyExists($key) === false || $overwrite === true) {
$_SESSION[$key] = $value;
return true;
}
return false;
}
public function delete($key) {
if ($this->keyExists($key) === false) {
unset($_SESSION[$key]);
return true;
}
return false;
}
public static function id($new = false) {
if ($new === true && session_id()) {
session_regenerate_id(true);
}
return session_id() ? : false;
}
public static function destroy() {
if (self::id()) {
session_unset();
session_destroy();
session_write_close();
if (ini_get('session.use_cookies')) {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 4200, $params['path'], $params['domain'], $params['secure'], $params['httponly']);
}
}
}
protected function keyExists($key) {
return array_key_exists($key, $_SESSION);
}
public function __get($key) {
return $this->get($key);
}
public function __set($key, $value) {
$this->set($key, $value);
}
public function __unset($key) {
$this->delete($key);
}
public function __isset($key) {
return $this->exists($key);
}
}
In my bootstrap (index.php) I have the following code:
<?php
use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;
require '../vendor/autoload.php';
$app = new \Slim\App(array(
'debug' => true
));
$app->add($session = new Custom\Middleware\Session(array(
'name' => 'DevSession',
'autorefresh' => true,
'lifetime' => '60 minutes'
)));
$container = $app->getContainer();
$container['session'] = function () {
return new Custom\Session\SessionHelper();
};
$app->get('/', function (Request $request, Response $response) {
$this->session->set('time', time());
echo $this->session->get('time');
return $response;
});
// Run app
$app->run();
The if(session_id()) in the startSession() method of the class Session always returns false. But, the session is active in my $app though. I don’t really understand why the __invoke is called after each refresh of the page, the if(session_id()) returns false, but the session is still active. Can someone explain how this works?
The reason I’m asking is because I want to make a more secure PHP session class, with methods to check if the session has been hijacked for example. But if the session is never active, according to the Session middleware, I don’t know how to accomplish such a check.
Help?