‪TYPO3CMS  10.4
DatabaseSessionBackend.php
Go to the documentation of this file.
1 <?php
2 
3 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 
19 
20 use Doctrine\DBAL\DBALException;
28 
36 {
40  protected ‪$configuration = [];
41 
45  protected ‪$hasAnonymousSessions = false;
46 
54  public function ‪initialize(string $identifier, array ‪$configuration)
55  {
56  $this->hasAnonymousSessions = (bool)(‪$configuration['has_anonymous'] ?? false);
57  $this->configuration = ‪$configuration;
58  }
59 
67  public function ‪validateConfiguration(): bool
68  {
69  if (empty($this->configuration['table'])) {
70  throw new \InvalidArgumentException(
71  'The session backend "' . static::class . '" needs a "table" configuration.',
72  1442996707
73  );
74  }
75  return true;
76  }
77 
78  public function ‪hash(string $sessionId): string
79  {
80  // The sha1 hash ensures we have good length for the key.
81  $key = sha1(‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'] . 'core-session-backend');
82  // @todo md5 is used as be_sessions.ses_id field only supports 32 characters in stable branches
83  return hash_hmac('md5', $sessionId, $key);
84  }
85 
93  public function get(string $sessionId): array
94  {
95  $query = $this->‪getQueryBuilder();
96 
97  $query->select('*')
98  ->from($this->configuration['table'])
99  ->where($query->expr()->eq('ses_id', $query->createNamedParameter($this->hash($sessionId), \PDO::PARAM_STR)));
100 
101  $result = $query->execute()->fetch();
102 
103  if (!is_array($result)) {
104  // Check for a non-hashed-version, will be removed in TYPO3 v11
105  $query = $this->‪getQueryBuilder();
106 
107  $result = $query->select('*')
108  ->from($this->configuration['table'])
109  ->where($query->expr()->eq('ses_id', $query->createNamedParameter($sessionId, \PDO::PARAM_STR)))
110  ->execute()
111  ->fetch();
112  if (!is_array($result)) {
113  throw new SessionNotFoundException(
114  'The session with identifier ' . $sessionId . ' was not found ',
115  1481885483
116  );
117  }
118  }
119  return $result;
120  }
121 
128  public function remove(string $sessionId): bool
129  {
130  $query = $this->‪getQueryBuilder();
131  $query->delete($this->configuration['table'])
132  ->where(
133  $query->expr()->orX(
134  $query->expr()->eq('ses_id', $query->createNamedParameter($this->hash($sessionId), \PDO::PARAM_STR)),
135  $query->expr()->eq('ses_id', $query->createNamedParameter($sessionId, \PDO::PARAM_STR))
136  )
137  );
138 
139  return (bool)$query->execute();
140  }
141 
152  public function set(string $sessionId, array $sessionData): array
153  {
154  $sessionId = $this->‪hash($sessionId);
155  $sessionData['ses_id'] = $sessionId;
156  $sessionData['ses_tstamp'] = ‪$GLOBALS['EXEC_TIME'] ?? time();
157 
158  try {
159  $this->‪getConnection()->‪insert(
160  $this->configuration['table'],
161  $sessionData,
162  ['ses_data' => \PDO::PARAM_LOB]
163  );
164  } catch (DBALException $e) {
165  throw new SessionNotCreatedException(
166  'Session could not be written to database: ' . $e->getMessage(),
167  1481895005,
168  $e
169  );
170  }
171 
172  return $sessionData;
173  }
174 
185  public function ‪update(string $sessionId, array $sessionData): array
186  {
187  $hashedSessionId = $this->‪hash($sessionId);
188  $sessionData['ses_id'] = $hashedSessionId;
189  $sessionData['ses_tstamp'] = ‪$GLOBALS['EXEC_TIME'] ?? time();
190 
191  try {
192  // allow 0 records to be affected, happens when no columns where changed
193  $this->‪getConnection()->‪update(
194  $this->configuration['table'],
195  $sessionData,
196  ['ses_id' => $hashedSessionId],
197  ['ses_data' => \PDO::PARAM_LOB]
198  );
199  // Migrate old session data as well to remove old entries and promote them to migrated entries
200  $this->‪getConnection()->‪update(
201  $this->configuration['table'],
202  $sessionData,
203  ['ses_id' => $sessionId],
204  ['ses_data' => \PDO::PARAM_LOB]
205  );
206  } catch (DBALException $e) {
207  throw new SessionNotUpdatedException(
208  'Session with id ' . $sessionId . ' could not be updated: ' . $e->getMessage(),
209  1481889220,
210  $e
211  );
212  }
213  return $sessionData;
214  }
215 
222  public function ‪collectGarbage(int $maximumLifetime, int $maximumAnonymousLifetime = 0)
223  {
224  $query = $this->‪getQueryBuilder();
225 
226  $query->delete($this->configuration['table'])
227  ->where($query->expr()->lt('ses_tstamp', (int)(‪$GLOBALS['EXEC_TIME'] - (int)$maximumLifetime)))
228  ->andWhere($this->hasAnonymousSessions ? $query->expr()->eq('ses_anonymous', 0) : ' 1 = 1');
229  $query->execute();
230 
231  if ($maximumAnonymousLifetime > 0 && $this->hasAnonymousSessions) {
232  $query = $this->‪getQueryBuilder();
233  $query->delete($this->configuration['table'])
234  ->where($query->expr()->lt('ses_tstamp', (int)(‪$GLOBALS['EXEC_TIME'] - (int)$maximumAnonymousLifetime)))
235  ->andWhere($query->expr()->eq('ses_anonymous', 1));
236  $query->execute();
237  }
238  }
239 
245  public function ‪getAll(): array
246  {
247  $query = $this->‪getQueryBuilder();
248  $query->select('*')->from($this->configuration['table']);
249  return $query->execute()->fetchAll();
250  }
251 
255  protected function ‪getQueryBuilder(): QueryBuilder
256  {
257  return $this->‪getConnection()->‪createQueryBuilder();
258  }
259 
263  protected function ‪getConnection(): Connection
264  {
265  return GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($this->configuration['table']);
266  }
267 }
‪TYPO3\CMS\Core\Session\Backend\DatabaseSessionBackend\$configuration
‪array $configuration
Definition: DatabaseSessionBackend.php:39
‪TYPO3\CMS\Core\Session\Backend\DatabaseSessionBackend\validateConfiguration
‪bool validateConfiguration()
Definition: DatabaseSessionBackend.php:65
‪TYPO3\CMS\Core\Session\Backend\DatabaseSessionBackend\$hasAnonymousSessions
‪bool $hasAnonymousSessions
Definition: DatabaseSessionBackend.php:43
‪TYPO3\CMS\Core\Database\Connection\insert
‪int insert($tableName, array $data, array $types=[])
Definition: Connection.php:211
‪TYPO3\CMS\Core\Session\Backend\DatabaseSessionBackend\initialize
‪initialize(string $identifier, array $configuration)
Definition: DatabaseSessionBackend.php:52
‪TYPO3\CMS\Core\Session\Backend\DatabaseSessionBackend\getAll
‪array getAll()
Definition: DatabaseSessionBackend.php:243
‪TYPO3\CMS\Core\Session\Backend\HashableSessionBackendInterface
Definition: HashableSessionBackendInterface.php:21
‪TYPO3\CMS\Core\Session\Backend\Exception\SessionNotCreatedException
Definition: SessionNotCreatedException.php:24
‪TYPO3\CMS\Core\Session\Backend\DatabaseSessionBackend\update
‪array update(string $sessionId, array $sessionData)
Definition: DatabaseSessionBackend.php:183
‪TYPO3\CMS\Core\Database\Connection\update
‪int update($tableName, array $data, array $identifier, array $types=[])
Definition: Connection.php:302
‪TYPO3\CMS\Core\Database\Query\QueryBuilder
Definition: QueryBuilder.php:52
‪TYPO3\CMS\Core\Session\Backend\DatabaseSessionBackend\getQueryBuilder
‪QueryBuilder getQueryBuilder()
Definition: DatabaseSessionBackend.php:253
‪TYPO3\CMS\Core\Session\Backend\SessionBackendInterface
Definition: SessionBackendInterface.php:28
‪TYPO3\CMS\Core\Session\Backend\Exception\SessionNotUpdatedException
Definition: SessionNotUpdatedException.php:24
‪TYPO3\CMS\Core\Session\Backend\DatabaseSessionBackend\hash
‪hash(string $sessionId)
Definition: DatabaseSessionBackend.php:76
‪TYPO3\CMS\Core\Session\Backend
Definition: DatabaseSessionBackend.php:18
‪TYPO3\CMS\Core\Session\Backend\DatabaseSessionBackend\getConnection
‪Connection getConnection()
Definition: DatabaseSessionBackend.php:261
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:36
‪TYPO3\CMS\Core\Session\Backend\DatabaseSessionBackend
Definition: DatabaseSessionBackend.php:36
‪$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:220
‪TYPO3\CMS\Core\Database\Connection\createQueryBuilder
‪TYPO3 CMS Core Database Query QueryBuilder createQueryBuilder()
Definition: Connection.php:117
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Core\Session\Backend\Exception\SessionNotFoundException
Definition: SessionNotFoundException.php:24