Skip to content

[HttpFoundation component] Possible RedisSessionHandler and Session maxlifetime differents #34659

Closed
@rafaeltovar

Description

@rafaeltovar

Symfony version(s) affected: 4.4.0

Description

Option gc_maxlifetime doesn't work well, because RedisSessionHandler use a different variable for this purpose.

session.gc_maxlifetime will set on setOptions method of Session/Storage/NativeSessionStorage called on ___construct method, but Session/Storage/Handler/RedisSessionHandler set ttl property on his __construct, called before NativeSessionStorage::__construct.

How to reproduce

use Symfony\Component\HttpFoundation\Session\Storage\Handler\RedisSessionHandler;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;

ini_set('session.gc_maxlifetime',  60); // set session.gc_maxlifetime to 60

$handler = new RedisSessionHandler($predis); // $this->ttl = 60;

$storage = new NativeSessionStorage(['gc_maxlifetime' => 360], $handler); // set session.gc_maxlifetime = 360

$session = new Session($storage);
$session->start();
$session->set('uid', 1); // set expire on redis to 60

Possible Solution

// Symfony\Component\HttpFoundation\Session\Storage\Handler\RedisSessionHandler;
class RedisSessionHandler extends AbstractSessionHandler
{
    private $redis;
    /**
     * @var string Key prefix for shared environments
     */
    private $prefix;
    /**
     * @var int Time to live in seconds
     */
    private $ttl;
    /**
     * List of available options:
     *  * prefix: The prefix to use for the keys in order to avoid collision on the Redis server
     *  * ttl: The time to live in seconds.
     *
     * @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|RedisProxy|RedisClusterProxy $redis
     *
     * @throws \InvalidArgumentException When unsupported client or options are passed
     */
    public function __construct($redis, array $options = [])
    {
       //...
        $this->redis = $redis;
        $this->prefix = $options['prefix'] ?? 'sf_s';
        // $this->ttl = $options['ttl'] ?? (int) ini_get('session.gc_maxlifetime');
        $this->ttl = $options['ttl'] ?? 0;
    }
    // ...
    /**
     * {@inheritdoc}
     */
    protected function doWrite($sessionId, $data): bool
    {
       $ttl = $this->ttl > 0?  $this->ttl : (int) ini_get('session.gc_maxlifetime');
        $result = $this->redis->setEx($this->prefix.$sessionId, $ttl, $data);
        return $result && !$result instanceof ErrorInterface;
    }
    // ...
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions