diff --git a/core/authorize.php b/core/authorize.php index dbab02f39adb008938b363c163ae6782f8a7ed05..d033b7efb2825dcd87e78463b6b62921e6064242 100644 --- a/core/authorize.php +++ b/core/authorize.php @@ -51,6 +51,7 @@ * TRUE if the current user can run authorize.php, and FALSE if not. */ function authorize_access_allowed() { + \Drupal::service('session_manager')->start(); return Settings::get('allow_authorize_operations', TRUE) && \Drupal::currentUser()->hasPermission('administer software updates'); } diff --git a/core/core.services.yml b/core/core.services.yml index 9fe832403b249b613772af76d05218f6f1fba1be..9f5d6fc325bb92791a1d5a20499cb144575a91b0 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -475,11 +475,6 @@ services: arguments: ['@kernel'] tags: - { name: http_middleware, priority: 100 } - http_middleware.session: - class: Drupal\Core\StackMiddleware\Session - arguments: ['@session'] - tags: - - { name: http_middleware, priority: 50 } language_manager: class: Drupal\Core\Language\LanguageManager arguments: ['@language.default'] @@ -998,7 +993,7 @@ services: arguments: ['@module_handler', '@cache.discovery', '@language_manager', '@cache_tags.invalidator'] batch.storage: class: Drupal\Core\Batch\BatchStorage - arguments: ['@database', '@session', '@csrf_token'] + arguments: ['@database', '@session_manager', '@csrf_token'] tags: - { name: backend_overridable } replica_database_ignore__subscriber: @@ -1094,15 +1089,6 @@ services: session_configuration: class: Drupal\Core\Session\SessionConfiguration arguments: ['%session.storage.options%'] - session: - class: Symfony\Component\HttpFoundation\Session\Session - arguments: ['@session_manager', '@session.attribute_bag', '@session.flash_bag'] - session.flash_bag: - class: Symfony\Component\HttpFoundation\Session\Flash\FlashBag - public: false - session.attribute_bag: - class: Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag - public: false session_manager: class: Drupal\Core\Session\SessionManager arguments: ['@request_stack', '@database', '@session_manager.metadata_bag', '@session_configuration'] diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc index 34187f2c50b6539620e94fdfbe84beed535aaf25..f98c64d53bf61785c463a88d2f70fc73ec21dc25 100644 --- a/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -21,11 +21,9 @@ use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\Core\Url; use Drupal\language\Entity\ConfigurableLanguage; -use Symfony\Cmf\Component\Routing\RouteObjectInterface; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\Routing\Route; use GuzzleHttp\Exception\RequestException; @@ -398,6 +396,7 @@ function install_begin_request($class_loader, &$install_state) { $kernel->setSitePath($site_path); $kernel->boot(); $container = $kernel->getContainer(); + $container->get('request_stack')->push($request); // Register the file translation service. if (isset($GLOBALS['config']['locale.settings']['translation']['path'])) { @@ -443,15 +442,13 @@ function install_begin_request($class_loader, &$install_state) { if ($profile && !$module_handler->moduleExists($profile)) { $module_handler->addProfile($profile, $install_state['profiles'][$profile]->getPath()); } + // After setting up a custom and finite module list in a custom low-level + // bootstrap like here, ensure to use ModuleHandler::loadAll() so that + // ModuleHandler::isLoaded() returns TRUE, since that is a condition being + // checked by other subsystems (e.g., the theme system). + $module_handler->loadAll(); - // Load all modules and perform request related initialization. - $kernel->preHandle($request); - - // Initialize a route on this legacy request similar to - // \Drupal\Core\DrupalKernel::prepareLegacyRequest() since normal routing - // will not happen. - $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route('')); - $request->attributes->set(RouteObjectInterface::ROUTE_NAME, ''); + $kernel->prepareLegacyRequest($request); // Prepare for themed output. We need to run this at the beginning of the // page request to avoid a different theme accidentally getting set. (We also @@ -596,7 +593,7 @@ function install_run_task($task, &$install_state) { $response = batch_process($url, clone $url); if ($response instanceof Response) { // Save $_SESSION data from batch. - \Drupal::service('session')->save(); + \Drupal::service('session_manager')->save(); // Send the response. $response->send(); exit; @@ -1551,7 +1548,7 @@ function install_load_profile(&$install_state) { * An array of information about the current installation state. */ function install_bootstrap_full() { - \Drupal::service('session')->start(); + \Drupal::service('session_manager')->start(); } /** diff --git a/core/lib/Drupal/Core/Authentication/Provider/Cookie.php b/core/lib/Drupal/Core/Authentication/Provider/Cookie.php index e36275f2d5972bb824053916c74e7227cd961971..5f88c4789ceae3852446399130d979f8c3aaa022 100644 --- a/core/lib/Drupal/Core/Authentication/Provider/Cookie.php +++ b/core/lib/Drupal/Core/Authentication/Provider/Cookie.php @@ -17,11 +17,28 @@ */ class Cookie implements AuthenticationProviderInterface { + /** + * The session manager. + * + * @var \Drupal\Core\Session\SessionManagerInterface + */ + protected $sessionManager; + + /** + * Constructs a new Cookie authentication provider instance. + * + * @param \Drupal\Core\Session\SessionManagerInterface $session_manager + * The session manager. + */ + public function __construct(SessionManagerInterface $session_manager) { + $this->sessionManager = $session_manager; + } + /** * {@inheritdoc} */ public function applies(Request $request) { - return $request->hasSession(); + return TRUE; } /** @@ -30,11 +47,10 @@ public function applies(Request $request) { public function authenticate(Request $request) { // Global $user is deprecated, but the session system is still based on it. global $user; - - if ($request->getSession()->start()) { + $this->sessionManager->start(); + if ($this->sessionManager->isStarted()) { return $user; } - return NULL; } @@ -42,6 +58,7 @@ public function authenticate(Request $request) { * {@inheritdoc} */ public function cleanup(Request $request) { + $this->sessionManager->save(); } /** diff --git a/core/lib/Drupal/Core/Batch/BatchStorage.php b/core/lib/Drupal/Core/Batch/BatchStorage.php index 5742fd2dbcf3427bf61081580ce63a421acd04f6..da0fe94764d0f5356233a10ab758b571770ac486 100644 --- a/core/lib/Drupal/Core/Batch/BatchStorage.php +++ b/core/lib/Drupal/Core/Batch/BatchStorage.php @@ -8,7 +8,7 @@ namespace Drupal\Core\Batch; use Drupal\Core\Database\Connection; -use Symfony\Component\HttpFoundation\Session\SessionInterface; +use Drupal\Core\Session\SessionManager; use Drupal\Core\Access\CsrfTokenGenerator; class BatchStorage implements BatchStorageInterface { @@ -21,11 +21,11 @@ class BatchStorage implements BatchStorageInterface { protected $connection; /** - * The session. + * The session manager. * - * @var \Symfony\Component\HttpFoundation\Session\SessionInterface + * @var \Drupal\Core\Session\SessionManager */ - protected $session; + protected $sessionManager; /** * The CSRF token generator. @@ -39,14 +39,14 @@ class BatchStorage implements BatchStorageInterface { * * @param \Drupal\Core\Database\Connection $connection * The database connection. - * @param \Symfony\Component\HttpFoundation\Session\SessionInterface $session - * The session. + * @param \Drupal\Core\Session\SessionManager $session_manager + * The session manager. * @param \Drupal\Core\Access\CsrfTokenGenerator $csrf_token * The CSRF token generator. */ - public function __construct(Connection $connection, SessionInterface $session, CsrfTokenGenerator $csrf_token) { + public function __construct(Connection $connection, SessionManager $session_manager, CsrfTokenGenerator $csrf_token) { $this->connection = $connection; - $this->session = $session; + $this->sessionManager = $session_manager; $this->csrfToken = $csrf_token; } @@ -55,7 +55,7 @@ public function __construct(Connection $connection, SessionInterface $session, C */ public function load($id) { // Ensure that a session is started before using the CSRF token generator. - $this->session->start(); + $this->sessionManager->start(); $batch = $this->connection->query("SELECT batch FROM {batch} WHERE bid = :bid AND token = :token", array( ':bid' => $id, ':token' => $this->csrfToken->get($id), @@ -100,7 +100,7 @@ public function cleanup() { */ public function create(array $batch) { // Ensure that a session is started before using the CSRF token generator. - $this->session->start(); + $this->sessionManager->start(); $this->connection->insert('batch') ->fields(array( 'bid' => $batch['id'], diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php index bfa2c980128f73f597d016822763f8a7c0244b8d..bc36c15fc087dbb3ff78237fb0099b77d2daf395 100644 --- a/core/lib/Drupal/Core/DrupalKernel.php +++ b/core/lib/Drupal/Core/DrupalKernel.php @@ -571,9 +571,8 @@ public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = public function prepareLegacyRequest(Request $request) { $this->boot(); $this->preHandle($request); - // Setup services which are normally initialized from within stack - // middleware or during the request kernel event. - $request->setSession($this->container->get('session')); + // Enter the request scope so that current_user service is available for + // locale/translation sake. $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route('')); $request->attributes->set(RouteObjectInterface::ROUTE_NAME, ''); $this->container->get('request_stack')->push($request); @@ -719,16 +718,6 @@ protected function initializeContainer($rebuild = FALSE) { if ($session_manager_started) { $this->container->get('session_manager')->start(); } - - // The request stack is preserved accross container rebuilds. Reinject the - // new session into the master request if one was present before. - if (($request_stack = $this->container->get('request_stack', ContainerInterface::NULL_ON_INVALID_REFERENCE))) { - if ($request = $request_stack->getMasterRequest()) { - if ($request->hasSession()) { - $request->setSession($this->container->get('session')); - } - } - } \Drupal::setContainer($this->container); // If needs dumping flag was set, dump the container. diff --git a/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionHtmlSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionHtmlSubscriber.php index f757aa7ee1b7c2e5cf9c4fc91d3b78c86fb4667e..9535abf5b6ffdef8852c73cf733d0ee4f1fcdd42 100644 --- a/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionHtmlSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionHtmlSubscriber.php @@ -111,11 +111,6 @@ protected function makeSubrequest(GetResponseForExceptionEvent $event, $path, $s // Persist the 'exception' attribute to the subrequest. $sub_request->attributes->set('exception', $request->attributes->get('exception')); - // Carry over the session to the subrequest. - if ($session = $request->getSession()) { - $sub_request->setSession($session); - } - $response = $this->httpKernel->handle($sub_request, HttpKernelInterface::SUB_REQUEST); $response->setStatusCode($status_code); $event->setResponse($response); diff --git a/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php b/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php index 83a7845156c4a72e4d6d2af023dc7b84f7ffdcb6..96b5e73de25d4c5a2ccf652266759b4ea03101d8 100644 --- a/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php +++ b/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php @@ -59,6 +59,9 @@ public function register(ContainerBuilder $container) { // @todo Convert installer steps into routes; add an installer.routing.yml. $definition = $container->getDefinition('router.builder'); $definition->setClass('Drupal\Core\Installer\InstallerRouteBuilder'); + + // Remove dependencies on Drupal's default session handling. + $container->removeDefinition('authentication.cookie'); } /** diff --git a/core/lib/Drupal/Core/Session/SessionManager.php b/core/lib/Drupal/Core/Session/SessionManager.php index 2a143b73822b478afc1604267071dca7f2ac3cc1..c354cec825027956f6e197f69e3114a0f19ce125 100644 --- a/core/lib/Drupal/Core/Session/SessionManager.php +++ b/core/lib/Drupal/Core/Session/SessionManager.php @@ -338,7 +338,7 @@ protected function getSessionDataMask() { // Ignore attribute bags when they do not contain any data. foreach ($this->bags as $bag) { $key = $bag->getStorageKey(); - $mask[$key] = !empty($_SESSION[$key]); + $mask[$key] = empty($_SESSION[$key]); } return array_intersect_key($mask, $_SESSION); diff --git a/core/lib/Drupal/Core/StackMiddleware/Session.php b/core/lib/Drupal/Core/StackMiddleware/Session.php deleted file mode 100644 index b45a16ec7a2d560ed1a60d98f8330c252d8b397b..0000000000000000000000000000000000000000 --- a/core/lib/Drupal/Core/StackMiddleware/Session.php +++ /dev/null @@ -1,63 +0,0 @@ -httpKernel = $http_kernel; - $this->session = $session; - } - - /** - * {@inheritdoc} - */ - public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = TRUE) { - if ($type === self::MASTER_REQUEST) { - $request->setSession($this->session); - } - - $result = $this->httpKernel->handle($request, $type, $catch); - - if ($type === self::MASTER_REQUEST && $request->hasSession()) { - $request->getSession()->save(); - } - - return $result; - } - -} diff --git a/core/modules/comment/src/Controller/CommentController.php b/core/modules/comment/src/Controller/CommentController.php index 69be36aa03e908887752b1e40082db7db6c10ef0..84fbf72f0a2b1a5d650967ef179adda5a68dbd7e 100644 --- a/core/modules/comment/src/Controller/CommentController.php +++ b/core/modules/comment/src/Controller/CommentController.php @@ -130,10 +130,6 @@ public function commentPermalink(Request $request, CommentInterface $comment) { // @todo: Cleaner sub request handling. $redirect_request = Request::create($entity->url(), 'GET', $request->query->all(), $request->cookies->all(), array(), $request->server->all()); $redirect_request->query->set('page', $page); - // Carry over the session to the subrequest. - if ($session = $request->getSession()) { - $redirect_request->setSession($session); - } // @todo: Convert the pager to use the request object. $request->query->set('page', $page); return $this->httpKernel->handle($redirect_request, HttpKernelInterface::SUB_REQUEST); diff --git a/core/modules/system/tests/modules/session_test/session_test.services.yml b/core/modules/system/tests/modules/session_test/session_test.services.yml index 8ef2e204dec0150831c8cd0c428109a9d4b5a20b..281b09d2165facfcecf849302b8fe1a8dd2a673d 100644 --- a/core/modules/system/tests/modules/session_test/session_test.services.yml +++ b/core/modules/system/tests/modules/session_test/session_test.services.yml @@ -1,5 +1,6 @@ services: session_test.subscriber: class: Drupal\session_test\EventSubscriber\SessionTestSubscriber + arguments: ['@session_manager'] tags: - { name: event_subscriber } diff --git a/core/modules/system/tests/modules/session_test/src/EventSubscriber/SessionTestSubscriber.php b/core/modules/system/tests/modules/session_test/src/EventSubscriber/SessionTestSubscriber.php index a17cd5a48220685ea7848a5bb8bf02318f389446..9029093c64d09d99e62694671f29a001dd9f84d9 100644 --- a/core/modules/system/tests/modules/session_test/src/EventSubscriber/SessionTestSubscriber.php +++ b/core/modules/system/tests/modules/session_test/src/EventSubscriber/SessionTestSubscriber.php @@ -7,6 +7,7 @@ namespace Drupal\session_test\EventSubscriber; +use Drupal\Core\Session\SessionManagerInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpKernel\KernelEvents; @@ -18,6 +19,13 @@ */ class SessionTestSubscriber implements EventSubscriberInterface { + /** + * The session manager. + * + * @var \Drupal\Core\Session\SessionManagerInterface + */ + protected $sessionManager; + /** * Stores whether $_SESSION is empty at the beginning of the request. * @@ -25,6 +33,13 @@ class SessionTestSubscriber implements EventSubscriberInterface { */ protected $emptySession; + /** + * Constructs a new session test subscriber. + */ + public function __construct(SessionManagerInterface $session_manager) { + $this->sessionManager = $session_manager; + } + /** * Set header for session testing. * @@ -32,8 +47,7 @@ class SessionTestSubscriber implements EventSubscriberInterface { * The Event to process. */ public function onKernelRequestSessionTest(GetResponseEvent $event) { - $session = $event->getRequest()->getSession(); - $this->emptySession = (int) !($session && $session->start()); + $this->emptySession = (int) !$this->sessionManager->start(); } /** diff --git a/core/modules/user/src/Entity/User.php b/core/modules/user/src/Entity/User.php index a2c3a4703c2ece440c7b64e94a7c58559927cc4b..8be2e5e2e4498bac71eb6d736e1f8f2f6ea5cd90 100644 --- a/core/modules/user/src/Entity/User.php +++ b/core/modules/user/src/Entity/User.php @@ -128,7 +128,7 @@ public function postSave(EntityStorageInterface $storage, $update = TRUE) { if ($this->pass->value != $this->original->pass->value) { $session_manager->delete($this->id()); if ($this->id() == \Drupal::currentUser()->id()) { - \Drupal::service('session')->migrate(); + $session_manager->regenerate(); } } diff --git a/core/modules/user/user.module b/core/modules/user/user.module index e09ff0310ebdebfb535c5e6928974ed91f1fd6fc..86c063d436f8a9645b4e452a47ef4f71ba4d313c 100644 --- a/core/modules/user/user.module +++ b/core/modules/user/user.module @@ -609,7 +609,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_manager')->regenerate(); \Drupal::moduleHandler()->invokeAll('user_login', array($account)); } @@ -840,7 +840,7 @@ function _user_cancel($edit, $account, $method) { function _user_cancel_session_regenerate() { // Regenerate the users session instead of calling session_destroy() as we // want to preserve any messages that might have been set. - \Drupal::service('session')->migrate(); + \Drupal::service('session_manager')->regenerate(); } /** @@ -1484,10 +1484,6 @@ function user_logout() { \Drupal::moduleHandler()->invokeAll('user_logout', array($user)); // Destroy the current session, and reset $user to the anonymous user. - // Note: In Symfony the session is intended to be destroyed with - // Session::invalidate(). Regrettably this method is currently broken and may - // lead to the creation of spurious session records in the database. - // @see https://github.com/symfony/symfony/issues/12375 session_destroy(); } diff --git a/core/modules/user/user.services.yml b/core/modules/user/user.services.yml index 8a4f4f05ab4f489dc191f43e70b358999fd40a21..3b6e4516e63ca4b2f4efd20e5e5565efa0222c19 100644 --- a/core/modules/user/user.services.yml +++ b/core/modules/user/user.services.yml @@ -17,6 +17,7 @@ services: - { name: access_check, applies_to: _user_is_logged_in } authentication.cookie: class: Drupal\Core\Authentication\Provider\Cookie + arguments: ['@session_manager'] tags: - { name: authentication_provider, priority: 0 } cache_context.user: