Project

General

Profile

Actions

Bug #88866

closed

RedisSessionBackend issue when FE and BE Sessions are in distinct Redis DB

Added by Yann Weyer over 5 years ago. Updated almost 5 years ago.

Status:
Closed
Priority:
Should have
Assignee:
-
Category:
Locking / Session Handling
Target version:
-
Start date:
2019-07-30
Due date:
% Done:

100%

Estimated time:
TYPO3 Version:
8
PHP Version:
7.1
Tags:
redis, session,
Complexity:
Is Regression:
Sprint Focus:

Description

Symptoms

When using two distinct Sessions databases on the same Redis server, we observed FE keys in the BE database. It happens as soon as users have both a BE and a FE session, when extensions try to save data in the FE session.

Another user reported a similar problem in https://github.com/TYPO3-Solr/ext-solr/issues/1928

Cause

Debugging it a bit further, I isolated the following line in RedisSessionBackend.php :

        try {
            $this->connected = $this->redis->pconnect(
                $this->configuration['hostname'] ?? '127.0.0.1',
                $this->configuration['port'] ?? 6379
            );
        } catch (\RedisException $e) {
            $this->logger->alert('Could not connect to redis server.', ['exception' => $e]);
        }

Although I can't exactly explain why, it seems pconnect automatically shares the Redis connection between the two distinct Sessions backends, resulting in data being read or written in the wrong database.

Possible fixes

Use connect instead of pconnect

By replacing $this->redis->pconnect by $this->redis->connect, sessions are saved in correct database as intended. The drawback of this option is it might harm the performance under high load.

Define a persistent_id for each database

To ensure Redis connection stay independant, pconnect offers a persistent_id to tell them apart. It might make sense to include the Redis target database to said id:

            $this->connected = $this->redis->pconnect(
                $this->configuration['hostname'] ?? '127.0.0.1',
                $this->configuration['port'] ?? 6379,
                0, /* timeout parameter (0 by default) */
                get_class($this) . $this->configuration['database'] /* persistent_id: class + target database */
            );

Using get_class($this) . $this->configuration['database'] as a persistent_id is only a test from me, perhaps it would make sense to keep it more general? (e.g: a hash of hostname + port + database?)

It might also worth checking if the Redis caching backend might benefit from a similar persistent_id introduction when using persistent connections.

Mention this as a requirement in the documentation

If, for any reason, it is intended to have only one database for both BE and FE sessions, I think it should be mentioned in the documentation of the SessionStorageFramework

Actions

Also available in: Atom PDF