juliangut / sessionware
PSR7 session management middleware
Requires
- php: >=5.5
- league/event: ^2.1
- psr/http-message: ^1.0
- symfony/polyfill-php56: ^1.0
- symfony/polyfill-php70: ^1.0
Requires (Dev)
- phpmd/phpmd: ^2.2
- phpunit/phpunit: ^4.5|^5.0
- sebastian/phpcpd: ^2.0
- sensiolabs/security-checker: ^3.0
- squizlabs/php_codesniffer: ^2.0
- zendframework/zend-diactoros: ^1.3
README
SessionWare
A PSR7 session management middleware.
Automatic control of session timeout.
Generates a 80 character long session_id using random_bytes
, a truly cryptographically secure pseudo-random generator, instead of session.hash_function
hash algorithm.
Important considerations
Be aware that this middleware needs some session ini
settings to be set to specific values:
session.use_trans_sid
to false
session.use_cookies
to true
session.use_only_cookies
to true
session.use_strict_mode
to false
session.cache_limiter
to '' (empty string)
This values will prevent session headers to be automatically sent to user. It's the developer's responsibility to include corresponding cache headers in response object, which should be the case in the first place instead of relying on PHP environment settings.
You can use juliangut/cacheware which will automatically set the corrent session ini settings and add the corresponding cache headers to response object.
By using session_regenerate_id()
during execution cryptographically secure session ID will be replaced by default PHP session.hash_function
generated ID (not really secure). To prevent this from happening use \Jgut\Middleware\Session
helper method regenerateSessionId()
instead:
\Jgut\Middleware\Session::regenerateSessionId();
Installation
Composer
composer require juliangut/sessionware
Usage
require 'vendor/autoload.php'; use \Jgut\Middleware\SessionWare $configuration = [ 'name' => 'myProjectSessionName', 'lifetime' => 1800, // 30 minutes ]; $sessionMiddleware = new SessionWare($configuration); // Get $request and $response from PSR7 implementation $request = new Request(); $response = new Response(); $response = $sessionMiddleware($request, $response, function() { }); // Session is started, populated with default parameters and response has session cookie header
Integrated on a Middleware workflow:
require 'vendor/autoload.php'; use \Jgut\Middleware\SessionWare $configuration = [ 'name' => 'myProjectSessionName', 'lifetime' => SessionWare::SESSION_LIFETIME_NORMAL, // 15 minutes ]; $defaultSessionParams = [ 'default_timezone' => 'UTC', ] $app = new \YourMiddlewareAwareApplication(); $app->addMiddleware(new SessionWare($configuration, $defaultParameters)); $app->run();
Session helper
There is an extra Session helper to abstract access to the $_SESSION variable. This is usefull for example when NOT accessing global variables is important for you (such as when using PHP_MD to statically analise your code)
In order to benefit from SessionWare cryptographically secure generated session id DO use
$session = new \Jgut\Middleware\Session;
$session->regenerate();
// Or can be called statically
\Jgut\Middleware\Session::regenerateSessionId()
Config
$sessionMiddleware = new SessionWare([ 'timeoutKey' => '__SESSIONWARE_TIMEOUT_TIMESTAMP__' 'name' => 'SessionWareSession', 'savePath' => '/tmp/SessionWareSession', 'lifetime' => SessionWare::SESSION_LIFETIME_NORMAL, 'domain' => 'http://example.com', 'path' => '/', 'secure' => false, 'httponly' => true, ]);
Default values mimic those provided by default PHP installation so the middleware can be used as a direct drop-in with automatic session timeout control
timeoutKey
Parameter stored in session array to control session validity according to lifetime
parameter. Defaults to
\Jgut\Middleware\SessionWare::SESSION_TIMEOUT_KEY_DEFAULT = '__SESSIONWARE_TIMEOUT_TIMESTAMP__';
It is advised not to change this value unless it conflicts with one of your own session keys (which is unlikely if not directly impossible)
name
Assigns session name, default PHP PHPSESSID
session name will be used if none provided.
Review Important note below.
savePath
This configuration is used only if default 'files' session save handler is selected in session.save_handler
.
Assigns the path to store session files. If none provided sys_get_temp_dir()
, session_save_path()
and session 'name' will be used to compose a unique path.
Review Important note below.
lifetime
Number of seconds for the session to be considered valid. uses session.gc_maxlifetime
and session.cookie_lifetime
to discover PHP configured session lifetime if none provided. Finally it defaults to SessionWare::SESSION_LIFETIME_DEFAULT
(24 minutes) if previous values are not available or their value is zero.
There are six session lifetime constants available for convenience:
- SESSION_LIFETIME_FLASH = 5 minutes
- SESSION_LIFETIME_SHORT = 10 minutes
- SESSION_LIFETIME_NORMAL = 15 minutes
- SESSION_LIFETIME_DEFAULT = 24 minutes
- SESSION_LIFETIME_EXTENDED = 1 hour
- SESSION_LIFETIME_INFINITE =
PHP_INT_MAX
, around 1145 years on x86_64 architecture
path, domain, secure and httponly
Shortcuts to session.cookie_path
, session.cookie_domain
, session.cookie_secure
and session.cookie_httponly
. If not provided configured cookie params will be used, so can be set using session_set_cookie_params()
before middleware run.
Events
You can listen to timeout events to perform actions accordingly. There are currently two events
pre.session_timeout
triggered right before session is wiped when session timeout is reachedpost.session_timeout
triggered right after session has been restarted due to session timeout
Events provide sessionId as parameter:
$sessionware = new SessionWare($configuration); $sessionware->addListener('pre.session_timeout', function($sessionId) { echo sprintf('session "%s" timed out', $sessionId); }) $sessionware->addListener('post.session_timeout', function($sessionId) { echo sprintf('new session "%s" created', $sessionId); })
Important note
Using default 'files' session save handler
If you define a session 'lifetime' you MUST set a session 'savePath' or a session 'name' (different to PHPSESSID
). This is to separate session files from other PHP scripts session files, for the garbage collector to handle expired files removal correctly.
Be aware that if this condition is not met starting a session might remove session files from other script/application as they are all located in the same directory and there is no way for the garbage collector to tell which script/application they belong to.
Using custom session save handler
Distinguishing between different script/application session files shouldn't be a problem in this case. But be carefull not to send cookie headers (setcookie
) directly to the client but to include them in the response object instead.
Register your custom session save handler before running this middleware to prevent savePath to be created.
Contributing
Found a bug or have a feature request? Please open a new issue. Have a look at existing issues before.
See file CONTRIBUTING.md
License
See file LICENSE included with the source code for a copy of the license terms.