diff --git a/core/core.services.yml b/core/core.services.yml
index 9d40627..207cd55 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -47,6 +47,11 @@ services:
     arguments: ['@request_stack']
     tags:
       - { name: cache.context}
+  cache_context.session_value:
+    class: Drupal\Core\Cache\Context\SessionValueCacheContext
+    arguments: ['@request_stack']
+    tags:
+      - { name: cache.context}
   cache_context.request_format:
     class: Drupal\Core\Cache\Context\RequestFormatCacheContext
     arguments: ['@request_stack']
diff --git a/core/lib/Drupal/Core/Cache/Context/SessionValueCacheContext.php b/core/lib/Drupal/Core/Cache/Context/SessionValueCacheContext.php
new file mode 100644
index 0000000..4a6b193
--- /dev/null
+++ b/core/lib/Drupal/Core/Cache/Context/SessionValueCacheContext.php
@@ -0,0 +1,40 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Cache\Context\SessionValueCacheContext.
+ */
+
+namespace Drupal\Core\Cache\Context;
+
+use Drupal\Core\Cache\CacheableMetadata;
+
+/**
+ * Defines the SessionCacheContext service, for "per session" caching.
+ *
+ * Cache context ID: 'session_value:$path'.
+ */
+class SessionValueCacheContext extends RequestStackCacheContextBase implements CacheContextInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getLabel() {
+    return t('Session value');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCacheableMetadata() {
+    return new CacheableMetadata();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getContext($session_value = NULL) {
+    return serialize($this->requestStack->getCurrentRequest()->getSession()->get($session_value));
+  }
+
+}
diff --git a/core/modules/views/src/Plugin/views/exposed_form/ExposedFormPluginBase.php b/core/modules/views/src/Plugin/views/exposed_form/ExposedFormPluginBase.php
index d17f70c..dc98c3f 100644
--- a/core/modules/views/src/Plugin/views/exposed_form/ExposedFormPluginBase.php
+++ b/core/modules/views/src/Plugin/views/exposed_form/ExposedFormPluginBase.php
@@ -316,8 +316,8 @@ public function resetForm(&$form, FormStateInterface $form_state) {
     // remember settings.
     $display_id = ($this->view->display_handler->isDefaulted('filters')) ? 'default' : $this->view->current_display;
 
-    if (isset($_SESSION['views'][$this->view->storage->id()][$display_id])) {
-      unset($_SESSION['views'][$this->view->storage->id()][$display_id]);
+    if ($this->view->getRequest()->getSession()->has("views:{$this->view->storage->id()}:{$display_id}")) {
+      $this->view->getRequest()->getSession()->remove("views:{$this->view->storage->id()}:{$display_id}");
     }
 
     // Set the form to allow redirect.
diff --git a/core/modules/views/src/Plugin/views/filter/FilterPluginBase.php b/core/modules/views/src/Plugin/views/filter/FilterPluginBase.php
index d2e9fe8..31a2390 100644
--- a/core/modules/views/src/Plugin/views/filter/FilterPluginBase.php
+++ b/core/modules/views/src/Plugin/views/filter/FilterPluginBase.php
@@ -1305,22 +1305,24 @@ public function storeGroupInput($input, $status) {
 
     // False means that we got a setting that means to recurse ourselves,
     // so we should erase whatever happened to be there.
-    if ($status === FALSE && isset($_SESSION['views'][$this->view->storage->id()][$display_id])) {
-      $session = &$_SESSION['views'][$this->view->storage->id()][$display_id];
+    if ($status === FALSE && $this->view->getRequest()->getSession()->has("views:{$this->view->storage->id()}:{$display_id}")) {
+      $session = $this->view->getRequest()->getSession()->get("views:{$this->view->storage->id()}:{$display_id}");
 
       if (isset($session[$this->options['group_info']['identifier']])) {
         unset($session[$this->options['group_info']['identifier']]);
       }
+      $this->view->getRequest()->getSession()->set("views:{$this->view->storage->id()}:{$display_id}", $session);
     }
 
     if ($status !== FALSE) {
-      if (!isset($_SESSION['views'][$this->view->storage->id()][$display_id])) {
-        $_SESSION['views'][$this->view->storage->id()][$display_id] = array();
+      if (!$this->view->getRequest()->getSession()->has("views:{$this->view->storage->id()}:{$display_id}")) {
+        $this->view->getRequest()->getSession()->set("views:{$this->view->storage->id()}:{$display_id}", []);
       }
 
-      $session = &$_SESSION['views'][$this->view->storage->id()][$display_id];
+      $session = $this->view->getRequest()->getSession()->get("views:{$this->view->storage->id()}:{$display_id}");
 
       $session[$this->options['group_info']['identifier']] = $input[$this->options['group_info']['identifier']];
+      $this->view->getRequest()->getSession()->set("views:{$this->view->storage->id()}:{$display_id}", $session);
     }
   }
 
@@ -1397,8 +1399,8 @@ public function storeExposedInput($input, $status) {
 
     // False means that we got a setting that means to recurse ourselves,
     // so we should erase whatever happened to be there.
-    if (!$status && isset($_SESSION['views'][$this->view->storage->id()][$display_id])) {
-      $session = &$_SESSION['views'][$this->view->storage->id()][$display_id];
+    if (!$status && $this->view->getRequest()->getSession()->has("views:{$this->view->storage->id()}:{$display_id}")) {
+      $session = $this->view->getRequest()->getSession()->get("views:{$this->view->storage->id()}:{$display_id}");
       if ($operator && isset($session[$this->options['expose']['operator_id']])) {
         unset($session[$this->options['expose']['operator_id']]);
       }
@@ -1406,20 +1408,22 @@ public function storeExposedInput($input, $status) {
       if (isset($session[$this->options['expose']['identifier']])) {
         unset($session[$this->options['expose']['identifier']]);
       }
+      $this->view->getRequest()->getSession()->set("views:{$this->view->storage->id()}:{$display_id}", $session);
     }
 
     if ($status) {
-      if (!isset($_SESSION['views'][$this->view->storage->id()][$display_id])) {
-        $_SESSION['views'][$this->view->storage->id()][$display_id] = array();
+      if (!$this->view->getRequest()->getSession()->has("views:{$this->view->storage->id()}:{$display_id}")) {
+        $this->view->getRequest()->getSession()->set("views:{$this->view->storage->id()}:{$display_id}", []);
       }
 
-      $session = &$_SESSION['views'][$this->view->storage->id()][$display_id];
+      $session = $this->view->getRequest()->getSession()->get("views:{$this->view->storage->id()}:{$display_id}");
 
       if ($operator && isset($input[$this->options['expose']['operator_id']])) {
         $session[$this->options['expose']['operator_id']] = $input[$this->options['expose']['operator_id']];
       }
 
       $session[$this->options['expose']['identifier']] = $input[$this->options['expose']['identifier']];
+      $this->view->getRequest()->getSession()->set("views:{$this->view->storage->id()}:{$display_id}", $session);
     }
   }
 
@@ -1480,6 +1484,12 @@ public function getCacheContexts() {
     if ($this->isExposed()) {
       $cache_contexts[] = 'url';
     }
+
+    if (!empty($this->options['expose']['remember'])) {
+      $display_id = ($this->view->display_handler->isDefaulted('filters')) ? 'default' : $this->view->current_display;
+      $cache_contexts[] = 'session_value:views:' . $this->view->id() . ':' . $display_id;
+    }
+
     return $cache_contexts;
   }
 
diff --git a/core/modules/views/src/ViewExecutable.php b/core/modules/views/src/ViewExecutable.php
index 774e63c..268a280 100644
--- a/core/modules/views/src/ViewExecutable.php
+++ b/core/modules/views/src/ViewExecutable.php
@@ -666,8 +666,8 @@ public function getExposedInput() {
       // remember settings.
       $display_id = ($this->display_handler->isDefaulted('filters')) ? 'default' : $this->current_display;
 
-      if (empty($this->exposed_input) && !empty($_SESSION['views'][$this->storage->id()][$display_id])) {
-        $this->exposed_input = $_SESSION['views'][$this->storage->id()][$display_id];
+      if (empty($this->exposed_input) && $this->request->getSession()->has("views:{$this->storage->id()}:{$display_id}")) {
+        $this->exposed_input = $this->request->getSession()->get("views:{$this->storage->id()}:{$display_id}");
       }
     }
 
