‪TYPO3CMS  9.5
DatabaseSessionBackend.php
Go to the documentation of this file.
1 <?php
2 declare(strict_types = 1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
18 use Doctrine\DBAL\DBALException;
26 
34 {
38  protected ‪$configuration = [];
39 
43  protected ‪$hasAnonymousSessions = false;
44 
52  public function ‪initialize(string $identifier, array ‪$configuration)
53  {
54  $this->hasAnonymousSessions = (bool)(‪$configuration['has_anonymous'] ?? false);
55  $this->configuration = ‪$configuration;
56  }
57 
65  public function ‪validateConfiguration(): bool
66  {
67  if (empty($this->configuration['table'])) {
68  throw new \InvalidArgumentException(
69  'The session backend "' . static::class . '" needs a "table" configuration.',
70  1442996707
71  );
72  }
73  return true;
74  }
75 
76  public function ‪hash(string $sessionId): string
77  {
78  // The sha1 hash ensures we have good length for the key.
79  $key = sha1(‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'] . 'core-session-backend');
80  // @todo md5 is used as be_sessions.ses_id field only supports 32 characters in stable branches
81  return hash_hmac('md5', $sessionId, $key);
82  }
83 
91  public function get(string $sessionId): array
92  {
93  $query = $this->‪getQueryBuilder();
94 
95  $query->select('*')
96  ->from($this->configuration['table'])
97  ->where($query->expr()->eq('ses_id', $query->createNamedParameter($this->hash($sessionId), \PDO::PARAM_STR)));
98 
99  $result = $query->execute()->fetch();
100 
101  if (!is_array($result)) {
102  // Check for a non-hashed-version, will be removed in TYPO3 v11
103  $query = $this->‪getQueryBuilder();
104 
105  $result = $query->select('*')
106  ->from($this->configuration['table'])
107  ->where($query->expr()->eq('ses_id', $query->createNamedParameter($sessionId, \PDO::PARAM_STR)))
108  ->execute()
109  ->fetch();
110  if (!is_array($result)) {
111  throw new SessionNotFoundException(
112  'The session with identifier ' . $sessionId . ' was not found ',
113  1481885483
114  );
115  }
116  }
117  return $result;
118  }
119 
126  public function remove(string $sessionId): bool
127  {
128  $query = $this->‪getQueryBuilder();
129  $query->delete($this->configuration['table'])
130  ->where(
131  $query->expr()->orX(
132  $query->expr()->eq('ses_id', $query->createNamedParameter($this->hash($sessionId), \PDO::PARAM_STR)),
133  $query->expr()->eq('ses_id', $query->createNamedParameter($sessionId, \PDO::PARAM_STR))
134  )
135  );
136 
137  return (bool)$query->execute();
138  }
139 
150  public function set(string $sessionId, array $sessionData): array
151  {
152  $sessionId = $this->‪hash($sessionId);
153  $sessionData['ses_id'] = $sessionId;
154  $sessionData['ses_tstamp'] = ‪$GLOBALS['EXEC_TIME'] ?? time();
155 
156  try {
157  $this->‪getConnection()->‪insert(
158  $this->configuration['table'],
159  $sessionData,
160  ['ses_data' => \PDO::PARAM_LOB]
161  );
162  } catch (DBALException $e) {
163  throw new SessionNotCreatedException(
164  'Session could not be written to database: ' . $e->getMessage(),
165  1481895005,
166  $e
167  );
168  }
169 
170  return $sessionData;
171  }
172 
183  public function ‪update(string $sessionId, array $sessionData): array
184  {
185  $hashedSessionId = $this->‪hash($sessionId);
186  $sessionData['ses_id'] = $hashedSessionId;
187  $sessionData['ses_tstamp'] = ‪$GLOBALS['EXEC_TIME'] ?? time();
188 
189  try {
190  // allow 0 records to be affected, happens when no columns where changed
191  $this->‪getConnection()->‪update(
192  $this->configuration['table'],
193  $sessionData,
194  ['ses_id' => $hashedSessionId],
195  ['ses_data' => \PDO::PARAM_LOB]
196  );
197  // Migrate old session data as well to remove old entries and promote them to migrated entries
198  $this->‪getConnection()->‪update(
199  $this->configuration['table'],
200  $sessionData,
201  ['ses_id' => $sessionId],
202  ['ses_data' => \PDO::PARAM_LOB]
203  );
204  } catch (DBALException $e) {
205  throw new SessionNotUpdatedException(
206  'Session with id ' . $sessionId . ' could not be updated: ' . $e->getMessage(),
207  1481889220,
208  $e
209  );
210  }
211  return $sessionData;
212  }
213 
220  public function ‪collectGarbage(int $maximumLifetime, int $maximumAnonymousLifetime = 0)
221  {
222  $query = $this->‪getQueryBuilder();
223 
224  $query->delete($this->configuration['table'])
225  ->where($query->expr()->lt('ses_tstamp', (int)(‪$GLOBALS['EXEC_TIME'] - (int)$maximumLifetime)))
226  ->andWhere($this->hasAnonymousSessions ? $query->expr()->eq('ses_anonymous', 0) : ' 1 = 1');
227  $query->execute();
228 
229  if ($maximumAnonymousLifetime > 0 && $this->hasAnonymousSessions) {
230  $query = $this->‪getQueryBuilder();
231  $query->delete($this->configuration['table'])
232  ->where($query->expr()->lt('ses_tstamp', (int)(‪$GLOBALS['EXEC_TIME'] - (int)$maximumAnonymousLifetime)))
233  ->andWhere($query->expr()->eq('ses_anonymous', 1));
234  $query->execute();
235  }
236  }
237 
243  public function ‪getAll(): array
244  {
245  $query = $this->‪getQueryBuilder();
246  $query->select('*')->from($this->configuration['table']);
247  return $query->execute()->fetchAll();
248  }
249 
253  protected function ‪getQueryBuilder(): QueryBuilder
254  {
255  return $this->‪getConnection()->‪createQueryBuilder();
256  }
257 
261  protected function ‪getConnection(): Connection
262  {
263  return GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($this->configuration['table']);
264  }
265 }
‪TYPO3\CMS\Core\Session\Backend\DatabaseSessionBackend\$configuration
‪array $configuration
Definition: DatabaseSessionBackend.php:37
‪TYPO3\CMS\Core\Session\Backend\DatabaseSessionBackend\validateConfiguration
‪bool validateConfiguration()
Definition: DatabaseSessionBackend.php:63
‪TYPO3\CMS\Core\Session\Backend\DatabaseSessionBackend\$hasAnonymousSessions
‪bool $hasAnonymousSessions
Definition: DatabaseSessionBackend.php:41
‪TYPO3\CMS\Core\Database\Connection\insert
‪int insert($tableName, array $data, array $types=[])
Definition: Connection.php:193
‪TYPO3\CMS\Core\Session\Backend\DatabaseSessionBackend\initialize
‪initialize(string $identifier, array $configuration)
Definition: DatabaseSessionBackend.php:50
‪TYPO3\CMS\Core\Session\Backend\DatabaseSessionBackend\getAll
‪array getAll()
Definition: DatabaseSessionBackend.php:241
‪TYPO3\CMS\Core\Session\Backend\HashableSessionBackendInterface
Definition: HashableSessionBackendInterface.php:21
‪TYPO3\CMS\Core\Session\Backend\Exception\SessionNotCreatedException
Definition: SessionNotCreatedException.php:22
‪TYPO3\CMS\Core\Session\Backend\DatabaseSessionBackend\update
‪array update(string $sessionId, array $sessionData)
Definition: DatabaseSessionBackend.php:181
‪TYPO3\CMS\Core\Database\Connection\update
‪int update($tableName, array $data, array $identifier, array $types=[])
Definition: Connection.php:287
‪TYPO3\CMS\Core\Database\Query\QueryBuilder
Definition: QueryBuilder.php:47
‪TYPO3\CMS\Core\Session\Backend\DatabaseSessionBackend\getQueryBuilder
‪QueryBuilder getQueryBuilder()
Definition: DatabaseSessionBackend.php:251
‪TYPO3\CMS\Core\Session\Backend\SessionBackendInterface
Definition: SessionBackendInterface.php:26
‪TYPO3\CMS\Core\Session\Backend\Exception\SessionNotUpdatedException
Definition: SessionNotUpdatedException.php:22
‪TYPO3\CMS\Core\Session\Backend\DatabaseSessionBackend\hash
‪hash(string $sessionId)
Definition: DatabaseSessionBackend.php:74
‪TYPO3\CMS\Core\Session\Backend
Definition: DatabaseSessionBackend.php:3
‪TYPO3\CMS\Core\Session\Backend\DatabaseSessionBackend\getConnection
‪Connection getConnection()
Definition: DatabaseSessionBackend.php:259
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:31
‪TYPO3\CMS\Core\Session\Backend\DatabaseSessionBackend
Definition: DatabaseSessionBackend.php:34
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Core\Session\Backend\DatabaseSessionBackend\collectGarbage
‪collectGarbage(int $maximumLifetime, int $maximumAnonymousLifetime=0)
Definition: DatabaseSessionBackend.php:218
‪TYPO3\CMS\Core\Database\Connection\createQueryBuilder
‪TYPO3 CMS Core Database Query QueryBuilder createQueryBuilder()
Definition: Connection.php:110
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:44
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Core\Session\Backend\Exception\SessionNotFoundException
Definition: SessionNotFoundException.php:22