diff options
author | Max Kostikov <max@kostikov.co> | 2021-03-19 20:06:59 +0000 |
---|---|---|
committer | Mario <mario@mariovavti.com> | 2021-03-19 20:06:59 +0000 |
commit | 7476d8dccc184c8916962724def2c6aaf2a8a481 (patch) | |
tree | 422cbf1aa6d9af8a623e9207a50f7eeb4560d011 | |
parent | eb3a40b07ade552960637e831e7288da722f4c7f (diff) | |
download | volse-hubzilla-7476d8dccc184c8916962724def2c6aaf2a8a481.tar.gz volse-hubzilla-7476d8dccc184c8916962724def2c6aaf2a8a481.tar.bz2 volse-hubzilla-7476d8dccc184c8916962724def2c6aaf2a8a481.zip |
Implement custom Redis session backend
-rw-r--r-- | Zotlabs/Web/Session.php | 36 | ||||
-rw-r--r-- | Zotlabs/Web/SessionRedis.php | 123 |
2 files changed, 146 insertions, 13 deletions
diff --git a/Zotlabs/Web/Session.php b/Zotlabs/Web/Session.php index fe0a3fbf9..6f92a0319 100644 --- a/Zotlabs/Web/Session.php +++ b/Zotlabs/Web/Session.php @@ -29,34 +29,44 @@ class Session { /* * Set our session storage functions. */ - + if($this->custom_handler) { /* Custom handler (files, memached, redis..) */ $session_save_handler = strval(get_config('system', 'session_save_handler', Null)); $session_save_path = strval(get_config('system', 'session_save_path', Null)); - $session_gc_probability = intval(get_config('system', 'session_gc_probability', 1)); - $session_gc_divisor = intval(get_config('system', 'session_gc_divisor', 100)); - if(!$session_save_handler || !$session_save_path) { - logger('Session save handler or path not set.',LOGGER_NORMAL,LOG_ERR); + + if(is_null($session_save_handler) || is_null($session_save_path)) { + logger('Session save handler or path not set', LOGGER_NORMAL, LOG_ERR); } else { - ini_set('session.save_handler', $session_save_handler); - ini_set('session.save_path', $session_save_path); - ini_set('session.gc_probability', $session_gc_probability); - ini_set('session.gc_divisor', $session_gc_divisor); + // Check if custom sessions backend exists + $clsname = '\Zotlabs\Web\Session' . ucfirst(strtolower($session_save_handler)); + if (class_exists($clsname)) { + $handler = new $clsname($session_save_path); + } + else { + ini_set('session.save_handler', $session_save_handler); + ini_set('session.save_path', $session_save_path); + ini_set('session.gc_probability', intval(get_config('system', 'session_gc_probability', 1))); + ini_set('session.gc_divisor', intval(get_config('system', 'session_gc_divisor', 100))); + } } } else { - $handler = new \Zotlabs\Web\SessionHandler(); + $handler = new SessionHandler(); + } + + if (isset($handler)) { $this->handler = $handler; - $x = session_set_save_handler($handler,false); - if(! $x) - logger('Session save handler initialisation failed.',LOGGER_NORMAL,LOG_ERR); + $x = session_set_save_handler($handler, false); + if(! $x) + logger('Session save handler initialisation failed.',LOGGER_NORMAL,LOG_ERR); } + // Force cookies to be secure (https only) if this site is SSL enabled. // Must be done before session_start(). diff --git a/Zotlabs/Web/SessionRedis.php b/Zotlabs/Web/SessionRedis.php new file mode 100644 index 000000000..b4f5d54b3 --- /dev/null +++ b/Zotlabs/Web/SessionRedis.php @@ -0,0 +1,123 @@ +<?php + +namespace Zotlabs\Web; + + +class SessionRedis implements \SessionHandlerInterface { + + private $redis = null; + + + function __construct($connection) { + + $this->redis = new \Redis(); + + $credentials = parse_url($connection); + + try { + if (isset($credentials['path'])) + $this->redis->connect($credentials['path']); + else { + + if (isset($credentials['query'])) + $vars = parse_str($credentials['query']); + else + $vars = []; + + $this->redis->connect( + (isset($credentials['scheme']) ? $credentials['scheme'] . '://' : '') . $credentials['host'], + (isset($credentials['port']) ? $credentials['port'] : 6379), + (isset($vars['timeout']) ? $vars['timeout'] : 1), + null, + 0, + (isset($vars['read_timeout']) ? $vars['read_timeout'] : 0) + ); + + if (isset($vars['auth'])) + $this->redis->auth($vars['auth']); + } + } + catch(\RedisException $ex) { + logger('Error connecting to Redis: ' . $ex->getMessage()); + } + } + + + function open($s, $n) { + + return true; + } + + // IMPORTANT: if we read the session and it doesn't exist, create an empty record. + // We rely on this due to differing PHP implementation of session_regenerate_id() + // some which call read explicitly and some that do not. So we call it explicitly + // just after sid regeneration to force a record to exist. + + function read($id) { + + if ($id) { + $data = $this->redis->get($id); + + if ($data) + return $data; + else + $this->redis->setEx($id, 300, ''); + } + + return ''; + } + + + function write($id, $data) { + + // Pretend everything is hunky-dory, even though it isn't. + // There probably isn't anything we can do about it in any event. + // See: https://stackoverflow.com/a/43636110 + + if(! $id || ! $data) + return true; + + + // Unless we authenticate somehow, only keep a session for 5 minutes + // The viewer can extend this by performing any web action using the + // original cookie, but this allows us to cleanup the hundreds or + // thousands of empty sessions left around from web crawlers which are + // assigned cookies on each page that they never use. + + $expire = 300; + + if($_SESSION) { + if(array_key_exists('remember_me',$_SESSION) && intval($_SESSION['remember_me'])) + $expire = 60 * 60 * 24 * 365; + elseif(local_channel()) + $expire = 60 * 60 * 24 * 3; + elseif(remote_channel()) + $expire = 60 * 60 * 24 * 1; + } + + $this->redis->setEx($id, $expire, $data); + + return true; + } + + + function close() { + + return true; + } + + + function destroy ($id) { + + $this->redis->del($id); + + return true; + } + + + function gc($expire) { + + return true; + } + +} |