‪TYPO3CMS  ‪main
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\Exception as DBALException;
23 use TYPO3\CMS\Core\Database\Query\QueryBuilder;
28 
36 {
40  protected ‪$configuration = [];
41 
45  protected ‪$hasAnonymousSessions = false;
46 
53  public function ‪initialize(string ‪$identifier, array ‪$configuration)
54  {
55  $this->hasAnonymousSessions = (bool)(‪$configuration['has_anonymous'] ?? false);
56  $this->configuration = ‪$configuration;
57  }
58 
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  return hash_hmac('sha256', $sessionId, $key);
81  }
82 
89  public function get(string $sessionId): array
90  {
91  $query = $this->‪getQueryBuilder();
92  $query->select('*')
93  ->from($this->configuration['table'])
94  ->where($query->expr()->eq('ses_id', $query->createNamedParameter($this->hash($sessionId))));
95  $result = $query->executeQuery()->fetchAssociative();
96  if (!is_array($result)) {
98  'The session with identifier ' . $sessionId . ' was not found ',
99  1481885483
100  );
101  }
102  return $result;
103  }
104 
110  public function remove(string $sessionId): bool
111  {
112  $query = $this->‪getQueryBuilder();
113  $query->delete($this->configuration['table'])
114  ->where(
115  $query->expr()->or(
116  $query->expr()->eq('ses_id', $query->createNamedParameter($this->hash($sessionId))),
117  $query->expr()->eq('ses_id', $query->createNamedParameter($sessionId))
118  )
119  );
120 
121  return (bool)$query->executeStatement();
122  }
123 
132  public function set(string $sessionId, array $sessionData): array
133  {
134  $sessionId = $this->‪hash($sessionId);
135  $sessionData['ses_id'] = $sessionId;
136  $sessionData['ses_tstamp'] = ‪$GLOBALS['EXEC_TIME'] ?? time();
137 
138  try {
139  $this->‪getConnection()->insert(
140  $this->configuration['table'],
141  $sessionData,
142  ['ses_data' => ‪Connection::PARAM_LOB]
143  );
144  } catch (DBALException $e) {
145  throw new SessionNotCreatedException(
146  'Session could not be written to database: ' . $e->getMessage(),
147  1481895005,
148  $e
149  );
150  }
151 
152  return $sessionData;
153  }
154 
164  public function ‪update(string $sessionId, array $sessionData): array
165  {
166  $hashedSessionId = $this->‪hash($sessionId);
167  $sessionData['ses_id'] = $hashedSessionId;
168  $sessionData['ses_tstamp'] = ‪$GLOBALS['EXEC_TIME'] ?? time();
169 
170  try {
171  // allow 0 records to be affected, happens when no columns where changed
172  $this->‪getConnection()->update(
173  $this->configuration['table'],
174  $sessionData,
175  ['ses_id' => $hashedSessionId],
176  ['ses_data' => ‪Connection::PARAM_LOB]
177  );
178  } catch (DBALException $e) {
179  throw new SessionNotUpdatedException(
180  'Session with id ' . $sessionId . ' could not be updated: ' . $e->getMessage(),
181  1481889220,
182  $e
183  );
184  }
185  return $sessionData;
186  }
187 
194  public function ‪collectGarbage(int $maximumLifetime, int $maximumAnonymousLifetime = 0)
195  {
196  $query = $this->‪getQueryBuilder();
197 
198  $query->delete($this->configuration['table'])
199  ->where($query->expr()->lt('ses_tstamp', (int)(‪$GLOBALS['EXEC_TIME'] - (int)$maximumLifetime)))
200  ->andWhere($this->hasAnonymousSessions ? $query->expr()->neq('ses_userid', 0) : ' 1 = 1');
201  $query->executeStatement();
202 
203  if ($maximumAnonymousLifetime > 0 && $this->hasAnonymousSessions) {
204  $query = $this->‪getQueryBuilder();
205  $query->delete($this->configuration['table'])
206  ->where($query->expr()->lt('ses_tstamp', (int)(‪$GLOBALS['EXEC_TIME'] - (int)$maximumAnonymousLifetime)))
207  ->andWhere($query->expr()->eq('ses_userid', 0));
208  $query->executeStatement();
209  }
210  }
211 
217  public function ‪getAll(): array
218  {
219  $query = $this->‪getQueryBuilder();
220  $query->select('*')->from($this->configuration['table']);
221  return $query->executeQuery()->fetchAllAssociative();
222  }
223 
224  protected function ‪getQueryBuilder(): QueryBuilder
225  {
226  return $this->‪getConnection()->createQueryBuilder();
227  }
228 
229  protected function ‪getConnection(): ‪Connection
230  {
231  return GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($this->configuration['table']);
232  }
233 }
‪TYPO3\CMS\Core\Session\Backend\DatabaseSessionBackend\$configuration
‪array $configuration
Definition: DatabaseSessionBackend.php:39
‪TYPO3\CMS\Core\Session\Backend\DatabaseSessionBackend\$hasAnonymousSessions
‪bool $hasAnonymousSessions
Definition: DatabaseSessionBackend.php:43
‪TYPO3\CMS\Core\Session\Backend\DatabaseSessionBackend\initialize
‪initialize(string $identifier, array $configuration)
Definition: DatabaseSessionBackend.php:51
‪TYPO3\CMS\Core\Session\Backend\DatabaseSessionBackend\getAll
‪array getAll()
Definition: DatabaseSessionBackend.php:215
‪TYPO3\CMS\Core\Session\Backend\HashableSessionBackendInterface
Definition: HashableSessionBackendInterface.php:21
‪TYPO3\CMS\Core\Session\Backend\Exception\SessionNotCreatedException
Definition: SessionNotCreatedException.php:23
‪TYPO3\CMS\Core\Session\Backend\DatabaseSessionBackend\update
‪array update(string $sessionId, array $sessionData)
Definition: DatabaseSessionBackend.php:162
‪TYPO3\CMS\Core\Session\Backend\DatabaseSessionBackend\getQueryBuilder
‪getQueryBuilder()
Definition: DatabaseSessionBackend.php:222
‪TYPO3\CMS\Core\Session\Backend\DatabaseSessionBackend\validateConfiguration
‪validateConfiguration()
Definition: DatabaseSessionBackend.php:63
‪TYPO3\CMS\Core\Session\Backend\DatabaseSessionBackend\getConnection
‪getConnection()
Definition: DatabaseSessionBackend.php:227
‪TYPO3\CMS\Core\Session\Backend\SessionBackendInterface
Definition: SessionBackendInterface.php:28
‪TYPO3\CMS\Core\Session\Backend\Exception\SessionNotUpdatedException
Definition: SessionNotUpdatedException.php:23
‪TYPO3\CMS\Core\Session\Backend\DatabaseSessionBackend\hash
‪hash(string $sessionId)
Definition: DatabaseSessionBackend.php:74
‪TYPO3\CMS\Core\Session\Backend
Definition: DatabaseSessionBackend.php:18
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:41
‪TYPO3\CMS\Core\Session\Backend\DatabaseSessionBackend
Definition: DatabaseSessionBackend.php:36
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\Session\Backend\DatabaseSessionBackend\collectGarbage
‪collectGarbage(int $maximumLifetime, int $maximumAnonymousLifetime=0)
Definition: DatabaseSessionBackend.php:192
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Core\Session\Backend\Exception\SessionNotFoundException
Definition: SessionNotFoundException.php:23
‪TYPO3\CMS\Webhooks\Message\$identifier
‪identifier readonly string $identifier
Definition: FileAddedMessage.php:37
‪TYPO3\CMS\Core\Database\Connection\PARAM_LOB
‪const PARAM_LOB
Definition: Connection.php:62