SessionHandler.php 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. <?php
  2. namespace Drupal\Core\Session;
  3. use Drupal\Component\Utility\Crypt;
  4. use Drupal\Core\Database\Connection;
  5. use Drupal\Core\DependencyInjection\DependencySerializationTrait;
  6. use Drupal\Core\Utility\Error;
  7. use Symfony\Component\HttpFoundation\RequestStack;
  8. use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy;
  9. /**
  10. * Default session handler.
  11. */
  12. class SessionHandler extends AbstractProxy implements \SessionHandlerInterface {
  13. use DependencySerializationTrait;
  14. /**
  15. * The request stack.
  16. *
  17. * @var \Symfony\Component\HttpFoundation\RequestStack
  18. */
  19. protected $requestStack;
  20. /**
  21. * The database connection.
  22. *
  23. * @var \Drupal\Core\Database\Connection
  24. */
  25. protected $connection;
  26. /**
  27. * Constructs a new SessionHandler instance.
  28. *
  29. * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
  30. * The request stack.
  31. * @param \Drupal\Core\Database\Connection $connection
  32. * The database connection.
  33. */
  34. public function __construct(RequestStack $request_stack, Connection $connection) {
  35. $this->requestStack = $request_stack;
  36. $this->connection = $connection;
  37. }
  38. /**
  39. * {@inheritdoc}
  40. */
  41. public function open($save_path, $name) {
  42. return TRUE;
  43. }
  44. /**
  45. * {@inheritdoc}
  46. */
  47. public function read($sid) {
  48. $data = '';
  49. if (!empty($sid)) {
  50. // Read the session data from the database.
  51. $query = $this->connection
  52. ->queryRange('SELECT session FROM {sessions} WHERE sid = :sid', 0, 1, [':sid' => Crypt::hashBase64($sid)]);
  53. $data = (string) $query->fetchField();
  54. }
  55. return $data;
  56. }
  57. /**
  58. * {@inheritdoc}
  59. */
  60. public function write($sid, $value) {
  61. // The exception handler is not active at this point, so we need to do it
  62. // manually.
  63. try {
  64. $request = $this->requestStack->getCurrentRequest();
  65. $fields = [
  66. 'uid' => $request->getSession()->get('uid', 0),
  67. 'hostname' => $request->getClientIP(),
  68. 'session' => $value,
  69. 'timestamp' => REQUEST_TIME,
  70. ];
  71. $this->connection->merge('sessions')
  72. ->keys(['sid' => Crypt::hashBase64($sid)])
  73. ->fields($fields)
  74. ->execute();
  75. return TRUE;
  76. }
  77. catch (\Exception $exception) {
  78. require_once DRUPAL_ROOT . '/core/includes/errors.inc';
  79. // If we are displaying errors, then do so with no possibility of a
  80. // further uncaught exception being thrown.
  81. if (error_displayable()) {
  82. print '<h1>Uncaught exception thrown in session handler.</h1>';
  83. print '<p>' . Error::renderExceptionSafe($exception) . '</p><hr />';
  84. }
  85. return FALSE;
  86. }
  87. }
  88. /**
  89. * {@inheritdoc}
  90. */
  91. public function close() {
  92. return TRUE;
  93. }
  94. /**
  95. * {@inheritdoc}
  96. */
  97. public function destroy($sid) {
  98. // Delete session data.
  99. $this->connection->delete('sessions')
  100. ->condition('sid', Crypt::hashBase64($sid))
  101. ->execute();
  102. return TRUE;
  103. }
  104. /**
  105. * {@inheritdoc}
  106. */
  107. public function gc($lifetime) {
  108. // Be sure to adjust 'php_value session.gc_maxlifetime' to a large enough
  109. // value. For example, if you want user sessions to stay in your database
  110. // for three weeks before deleting them, you need to set gc_maxlifetime
  111. // to '1814400'. At that value, only after a user doesn't log in after
  112. // three weeks (1814400 seconds) will his/her session be removed.
  113. $this->connection->delete('sessions')
  114. ->condition('timestamp', REQUEST_TIME - $lifetime, '<')
  115. ->execute();
  116. return TRUE;
  117. }
  118. }