diff --git a/core/lib/Drupal/Core/Session/MetadataBag.php b/core/lib/Drupal/Core/Session/MetadataBag.php index 4b44739..6a3c8ca 100644 --- a/core/lib/Drupal/Core/Session/MetadataBag.php +++ b/core/lib/Drupal/Core/Session/MetadataBag.php @@ -56,7 +56,9 @@ public function getCsrfTokenSeed() { /** * Clear the CSRF token seed. */ - public function clearCsrfTokenSeed() { + public function stampNew($lifetime = null) + { + parent::stampNew($lifetime); unset($this->meta[static::CSRF_TOKEN_SEED]); } diff --git a/core/lib/Drupal/Core/Session/SessionManager.php b/core/lib/Drupal/Core/Session/SessionManager.php index 2c35259..b320118 100644 --- a/core/lib/Drupal/Core/Session/SessionManager.php +++ b/core/lib/Drupal/Core/Session/SessionManager.php @@ -124,16 +124,6 @@ public function start() { } if (empty($result)) { - // Randomly generate a session identifier for this request. This is - // necessary because \Drupal\user\SharedTempStoreFactory::get() wants to - // know the future session ID of a lazily started session in advance. - // - // @todo: With current versions of PHP there is little reason to generate - // the session id from within application code. Consider using the - // default php session id instead of generating a custom one: - // https://www.drupal.org/node/2238561 - $this->setId(Crypt::randomBytesBase64()); - // Initialize the session global and attach the Symfony session bags. $_SESSION = array(); $this->loadSession(); @@ -214,30 +204,7 @@ public function regenerate($destroy = FALSE, $lifetime = NULL) { return; } - // We do not support the optional $destroy and $lifetime parameters as long - // as #2238561 remains open. - if ($destroy || isset($lifetime)) { - throw new \InvalidArgumentException('The optional parameters $destroy and $lifetime of SessionManager::regenerate() are not supported currently'); - } - - if ($this->isStarted()) { - $old_session_id = $this->getId(); - } - session_id(Crypt::randomBytesBase64()); - - $this->getMetadataBag()->clearCsrfTokenSeed(); - - if (isset($old_session_id)) { - $params = session_get_cookie_params(); - $expire = $params['lifetime'] ? REQUEST_TIME + $params['lifetime'] : 0; - setcookie($this->getName(), $this->getId(), $expire, $params['path'], $params['domain'], $params['secure'], $params['httponly']); - $this->migrateStoredSession($old_session_id); - } - - if (!$this->isStarted()) { - // Start the session when it doesn't exist yet. - $this->startNow(); - } + return parent::regenerate($destroy, $lifetime); } /** @@ -327,19 +294,4 @@ protected function getSessionDataMask() { return array_intersect_key($mask, $_SESSION); } - /** - * Migrates the current session to a new session id. - * - * @param string $old_session_id - * The old session id. The new session id is $this->getId() unless - * $new_insecure_session_id is not empty. - */ - protected function migrateStoredSession($old_session_id) { - $fields = array('sid' => Crypt::hashBase64($this->getId())); - $this->connection->update('sessions') - ->fields($fields) - ->condition('sid', Crypt::hashBase64($old_session_id)) - ->execute(); - } - } diff --git a/core/modules/user/src/PrivateTempStore.php b/core/modules/user/src/PrivateTempStore.php index 79be710..3886fd9 100644 --- a/core/modules/user/src/PrivateTempStore.php +++ b/core/modules/user/src/PrivateTempStore.php @@ -7,6 +7,7 @@ namespace Drupal\user; +use Drupal\Component\Utility\Crypt; use Drupal\Component\Utility\SafeMarkup; use Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface; use Drupal\Core\Lock\LockBackendInterface; @@ -80,8 +81,10 @@ class PrivateTempStore { * of key/value pairs. * @param \Drupal\Core\Lock\LockBackendInterface $lockBackend * The lock object used for this data. - * @param mixed $owner - * The owner key to store along with the data (e.g. a user or session ID). + * @param \Drupal\Core\Session\AccountProxyInterface $current_user + * The current user. + * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack + * The request stack. * @param int $expire * The time to live for items, in seconds. */ @@ -211,6 +214,15 @@ protected function createkey($key) { * The owner. */ protected function getOwner() { - return $this->currentUser->id() ?: $this->requestStack->getCurrentRequest()->getSession()->getId(); + if ($this->currentUser->isAuthenticated()) { + return $this->currentUser->id(); + } + // Anonymous users needs special handling. + // @todo Fix me. + if (!isset($_SESSION['user_private_owner'])) { + $_SESSION['user_private_owner'] = Crypt::randomBytesBase64(); + } + return $_SESSION['user_private_owner']; } + } diff --git a/core/modules/user/src/PrivateTempStoreFactory.php b/core/modules/user/src/PrivateTempStoreFactory.php index bd62633..39af0dc 100644 --- a/core/modules/user/src/PrivateTempStoreFactory.php +++ b/core/modules/user/src/PrivateTempStoreFactory.php @@ -55,10 +55,14 @@ class PrivateTempStoreFactory { /** * Constructs a Drupal\user\PrivateTempStoreFactory object. * - * @param \Drupal\Core\Database\Connection $connection - * The connection object used for this data. + * @param \Drupal\Core\KeyValueStore\KeyValueExpirableFactoryInterface $storage_factory + * The storage factory creating the backend to store the data. * @param \Drupal\Core\Lock\LockBackendInterface $lockBackend * The lock object used for this data. + * @param \Drupal\Core\Session\AccountProxyInterface $current_user + * The current user. + * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack + * The request stack. * @param int $expire * The time to live for items, in seconds. */ diff --git a/core/modules/user/src/SharedTempStoreFactory.php b/core/modules/user/src/SharedTempStoreFactory.php index da2331d..b974f56 100644 --- a/core/modules/user/src/SharedTempStoreFactory.php +++ b/core/modules/user/src/SharedTempStoreFactory.php @@ -8,6 +8,7 @@ namespace Drupal\user; use Drupal\Component\Serialization\SerializationInterface; +use Drupal\Component\Utility\Crypt; use Drupal\Core\KeyValueStore\KeyValueExpirableFactoryInterface; use Drupal\Core\Lock\LockBackendInterface; use Symfony\Component\HttpFoundation\RequestStack; @@ -48,8 +49,8 @@ class SharedTempStoreFactory { /** * Constructs a Drupal\user\SharedTempStoreFactory object. * - * @param \Drupal\Core\Database\Connection $connection - * The connection object used for this data. + * @param \Drupal\Core\KeyValueStore\KeyValueExpirableFactoryInterface $storage_factory + * The storage factory creating the backend to store the data. * @param \Drupal\Core\Lock\LockBackendInterface $lockBackend * The lock object used for this data. * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack @@ -82,7 +83,18 @@ function get($collection, $owner = NULL) { // Use the currently authenticated user ID or the active user ID unless // the owner is overridden. if (!isset($owner)) { - $owner = \Drupal::currentUser()->id() ?: session_id(); + $account = \Drupal::currentUser(); + if ($account->isAuthenticated()) { + $owner = $account->id(); + } + else { + // Anonymous users needs special handling. + // @todo Fix me. + if (!isset($_SESSION['user_shared_owner'])) { + $_SESSION['user_shared_owner'] = Crypt::randomBytesBase64(); + } + $owner = $_SESSION['user_shared_owner']; + } } // Store the data for this collection in the database. diff --git a/core/modules/user/user.module b/core/modules/user/user.module index 1e6de88..bf246f9 100644 --- a/core/modules/user/user.module +++ b/core/modules/user/user.module @@ -528,7 +528,7 @@ function user_login_finalize(UserInterface $account) { // This is called before hook_user_login() in case one of those functions // fails or incorrectly does a redirect which would leave the old session // in place. - \Drupal::service('session')->migrate(); + \Drupal::service('session')->migrate(TRUE); \Drupal::service('session')->set('uid', $account->id()); \Drupal::moduleHandler()->invokeAll('user_login', array($account)); }