diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index 60b086a..47a78d5 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -3258,6 +3258,12 @@ function drupal_classloader($class_loader = NULL) {
     $loader->registerPrefixes($prefixes);
     $loader->registerNamespaces($namespaces);
 
+    // Fallback to Symfony SessionHandlerInterface for PHP < 5.4.0. This
+    // should be removed once we switched to composer autoload.
+    if (!interface_exists('SessionHandlerInterface', FALSE)) {
+      $loader->registerPrefix('SessionHandlerInterface', $namespaces['Symfony\Component\HttpFoundation'] . 'Symfony/Component/HttpFoundation/Resources/stubs');
+    }
+
     // Register the loader with PHP.
     $loader->register();
   }
diff --git a/core/lib/Drupal/Core/CoreBundle.php b/core/lib/Drupal/Core/CoreBundle.php
index 624c716..46766dd 100644
--- a/core/lib/Drupal/Core/CoreBundle.php
+++ b/core/lib/Drupal/Core/CoreBundle.php
@@ -106,6 +106,16 @@ public function build(ContainerBuilder $container) {
       ->addMethodCall('addSubscriber', array(new Reference('http_client_simpletest_subscriber')))
       ->addMethodCall('setUserAgent', array('Drupal (+http://drupal.org/)'));
 
+    // Register the session service.
+    $container->register('session.storage.backend', 'Drupal\Core\Session\Handler\DatabaseSessionHandler');
+    $container->register('session.storage.proxy', 'Drupal\Core\Session\Proxy\CookieOverrideProxy')
+      ->addArgument(new Reference('session.storage.backend'));
+    $container->register('session.storage', 'Drupal\Core\Session\Storage\DrupalSessionStorage')
+      ->addArgument('session.storage.options', array())
+      ->addArgument(new Reference('session.storage.proxy'));
+    $container->register('session', 'Drupal\Core\Session\Session')
+      ->addArgument(new Reference('session.storage'));
+
     // Register the EntityManager.
     $container->register('plugin.manager.entity', 'Drupal\Core\Entity\EntityManager');
 
diff --git a/core/lib/Drupal/Core/Session/Handler/DatabaseSessionHandler.php b/core/lib/Drupal/Core/Session/Handler/DatabaseSessionHandler.php
new file mode 100644
index 0000000..ea832fb
--- /dev/null
+++ b/core/lib/Drupal/Core/Session/Handler/DatabaseSessionHandler.php
@@ -0,0 +1,87 @@
+<?php
+
+/**
+ * @file
+ * Defines Drupal\Core\Session\Handler\DatabaseSessionHandler.
+ */
+
+namespace Drupal\Core\Session\Handler;
+
+/**
+ * Drupal database session handler, load and save sessions using the {sessions}
+ * table throughout DBTng.
+ */
+class DatabaseSessionHandler implements \SessionHandlerInterface {
+
+  /**
+   * implements SessionHandlerInterface::open().
+   */
+  public function open($savePath, $sessionName) {
+    return TRUE;
+  }
+
+  /**
+   * implements SessionHandlerInterface::close().
+   */
+  public function close() {
+    return TRUE;
+  }
+
+  /**
+   * implements SessionHandlerInterface::destroy().
+   */
+  public function destroy($sessionId) {
+    try {
+      db_delete('sessions')->condition('sid', $sessionId)->execute();
+    }
+    catch (\PDOException $e) {
+      throw new \RuntimeException(sprintf('PDOException was thrown when trying to manipulate session data: %s', $e->getMessage()), 0, $e);
+    }
+
+    return TRUE;
+  }
+
+  /**
+   * implements SessionHandlerInterface::gc().
+   */
+  public function gc($lifetime) {
+    try {
+      db_delete('sessions')->condition('timestamp', time() - $lifetime, '<')->execute();
+    }
+    catch (\PDOException $e) {
+      throw new \RuntimeException(sprintf('PDOException was thrown when trying to manipulate session data: %s', $e->getMessage()), 0, $e);
+    }
+
+    return TRUE;
+  }
+
+  /**
+   * implements SessionHandlerInterface::read().
+   */
+  public function read($sessionId) {
+    $data = db_query("SELECT s.* FROM {sessions} s WHERE s.sid = :sid", array(':sid' => $sessionId))->fetchObject();
+    return !empty($data) ? $data->session : '';
+  }
+
+  /**
+   * implements SessionHandlerInterface::write().
+   */
+  public function write($sessionId, $data) {
+    try {
+      db_merge('sessions')
+        ->key(array(
+          'sid' => $sessionId,
+        ))
+        ->fields(array(
+          'session' => $data,
+          'timestamp' => time(),
+        ))
+        ->execute();
+    }
+    catch (\PDOException $e) {
+      throw new \RuntimeException(sprintf('PDOException was thrown when trying to write session data: %s', $e->getMessage()), 0, $e);
+    }
+
+    return TRUE;
+  }
+}
diff --git a/core/lib/Drupal/Core/Session/Proxy/CookieOverrideProxy.php b/core/lib/Drupal/Core/Session/Proxy/CookieOverrideProxy.php
new file mode 100644
index 0000000..f38f483
--- /dev/null
+++ b/core/lib/Drupal/Core/Session/Proxy/CookieOverrideProxy.php
@@ -0,0 +1,159 @@
+<?php
+
+/**
+ * @file
+ * Defines Drupal\Core\Session\Proxy\CookieOverrideProxy.
+ */
+
+namespace Drupal\Core\Session\Proxy;
+
+use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy;
+
+// @todo Replace this at the correct place.
+// If a session cookie exists, initialize the session. Otherwise the
+// session is only started on demand in drupal_session_commit(), making
+// anonymous users not use a session cookie unless something is stored in
+// $_SESSION. This allows HTTP proxies to cache anonymous page views.
+
+/**
+ * Custom SessionHandlerProxy implementation that allows us to handle the HTTP
+ * and HTTPS session cookies manually, and enforce strong security measures for
+ * the session handling.
+ */
+class CookieOverrideProxy extends SessionHandlerProxy {
+
+  /**
+   * Default Constructor.
+   *
+   * @param \SessionHandlerInterface $handler
+   */
+  public function __construct(\SessionHandlerInterface $handler) {
+    parent::__construct($handler);
+
+    if ($id = $this->getIdFromCookie()) {
+      $this->setId($id);
+    }
+    else {
+      // Set a session identifier for this request. This is necessary because we
+      // lazily start sessions at the end of this request, and some processes
+      // (like drupal_get_token()) needs to know the future session ID i
+      // advance.
+      $GLOBALS['lazy_session'] = TRUE;
+
+      // Less random sessions (which are much faster to generate) are used for
+      // anonymous users than are generated in drupal_session_regenerate() when
+      // a user becomes authenticated.
+      $this->regenerateId();
+
+      /*
+       * @todo Restore HTTPS cookie
+      if ($is_https && variable_get('https', FALSE)) {
+        $insecure_session_name = substr(session_name(), 1);
+        $session_id = drupal_hash_base64(uniqid(mt_rand(), TRUE));
+        $_COOKIE[$insecure_session_name] = $session_id;
+      }
+       */
+    }
+  }
+
+  /**
+   * overrides \Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy::isSessionHandlerInterface().
+   */
+  public function isSessionHandlerInterface()
+  {
+      return true;
+  }
+
+  /**
+   * Get current session identifier from cookie, if any.
+   *
+   * @return string
+   *   Session identifier or NULL if none found.
+   */
+  protected function getIdFromCookie() {
+    $name = $this->getName();
+    if (!empty($_COOKIE[$name])) {
+      // @todo Restore HTTPS cookie
+      //|| ($GLOBALS['is_https'] && variable_get('https', FALSE) && !empty($_COOKIE[substr(session_name(), 1)]))) {
+      return $_COOKIE[$name];
+    }
+  }
+
+  protected function destroyCookies() {
+    if (headers_sent()) {
+      //throw new \RuntimeException('Failed to destroy cookies because headers have already been sent.');
+    }
+
+    $params = session_get_cookie_params();
+    // @todo Restore HTTPS cookie
+    setcookie($this->getName(), '', time() - 3600, $params['path'], $params['domain'], $params['secure'], $params['httponly']);
+  }
+
+  protected function sendCookies($id) {
+    if (headers_sent()) {
+      //throw new \RuntimeException('Failed to set cookies because headers have already been sent.');
+    }
+
+    $params = session_get_cookie_params();
+    $expire = $params['lifetime'] ? time() + $params['lifetime'] : 0;
+    // @todo Restore HTTPS cookie
+    setcookie($this->getName(), $id, $expire, $params['path'], $params['domain'], $params['secure'], $params['httponly']);
+  }
+
+  public function write($id, $data) {
+
+    if (!$this->isActive()) {
+      return FALSE;
+    }
+
+    // Cookie sending must be when we are sure we need to keep the session, this
+    // ensure the lazy session init. Lazy session init is abusive talking we are
+    // not lazy initializing the session, but lazy sending the session cookie
+    // instead. Each anonymous user will intrinsically have a session tied, which
+    // allows to generate tokens for forms and such, but if the session ends up
+    // empty, the cookies will not be sent and the session will not be saved on
+    // disk.
+    $this->sendCookies($id);
+
+    return (bool) $this->handler->write($id, $data);
+  }
+
+  public function destroy($id) {
+    $this->destroyCookies($id);
+
+    return (bool) $this->handler->destroy($id);
+  }
+
+  /**
+   * Generate new session identifier.
+   *
+   * The the session_regenerate_id() is hardcoded into Symfony's
+   * NativeSessionStorage implementation while all other session_*() functions
+   * are used as setters only in the AbstractProxy implementation. This feels
+   * wrong and we need to override it without doing invasive changes.
+   *
+   * @todo See if this implementation can be made apart of Symfony
+   *
+   * @see Drupal\Core\Session\Proxy\Storage\DrupalSessionStorage::regenerate()
+   *
+   * @param bool $destroy
+   *   (optional) If set to TRUE, destroy the old session.
+   *
+   * @return string
+   *   New session identifier.
+   */
+  public function regenerateId($destroy = FALSE) {
+    $id = drupal_hash_base64(uniqid(mt_rand(), TRUE) . drupal_random_bytes(55));
+
+    // Do not call parent::setId() here, else it will throw exceptions because
+    // during session identifier regeneration, this component is considered as
+    // active.
+    session_id($id);
+
+    if ($destroy) {
+      $this->destroyCookies();
+    }
+
+    return TRUE;
+  }
+}
diff --git a/core/lib/Drupal/Core/Session/Session.php b/core/lib/Drupal/Core/Session/Session.php
new file mode 100644
index 0000000..f014d05
--- /dev/null
+++ b/core/lib/Drupal/Core/Session/Session.php
@@ -0,0 +1,130 @@
+<?php
+
+/**
+ * @file
+ * Defines Drupal\Core\Session\Session.
+ */
+
+namespace Drupal\Core\Session;
+
+use Symfony\Component\HttpFoundation\Session\Session as BaseSession;
+use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
+
+/**
+ * Overrides Symfony's Session object in order to implement Drupal specific
+ * session features, such as lazy cookie sending and explicit session save
+ * disabling.
+ */
+class Session extends BaseSession {
+
+  /**
+   * Keep track of the save enabled state.
+   *
+   * @var bool
+   */
+  protected $saveEnabled = TRUE;
+
+  /**
+   * Keep track fo the save handler state when disabling session write.
+   *
+   * @var bool
+   */
+  protected $lastSaveHandlerState;
+
+  /**
+   * Enable session save, at commit time session will be saved by the session
+   * handler and session token will be sent.
+   */
+  public function enableSave() {
+    $this->saveEnabled = TRUE;
+
+    if (null !== $this->lastSaveHandlerState && $this->lastSaveHandlerState) {
+      $this->storage->getSaveHandler()->setActive($this->lastSaveHandlerState);
+    }
+  }
+
+  /**
+   * Disable session save, at commit time session save will be skipped and
+   * session token will not be sent to client.
+   *
+   * This function allows the caller to temporarily disable writing of
+   * session data, should the request end while performing potentially
+   * dangerous operations, such as manipulating the global $user object.
+   * See http://drupal.org/node/218104 for usage.
+   */
+  public function disableSave() {
+    $this->saveEnabled = FALSE;
+
+    // As a side effect, the save handler in some occasions can be reached by
+    // either PHP native session handling either Symfony session handling. By
+    // disabling it manually we ensure it won't save anything behind our back.
+    $saveHandler = $this->storage->getSaveHandler();
+
+    if ($this->lastSaveHandlerState = $saveHandler->isActive()) {
+       $saveHandler->setActive(FALSE);
+    }
+  }
+
+  /**
+   * Is the session save enabled.
+   *
+   * @return bool
+   */
+  public function isSaveEnabled() {
+    return $this->saveEnabled;
+  }
+
+  /**
+   * Does this session is empty.
+   *
+   * Note:
+   *   Bags can not be directly accessed via protected attributes, and they
+   *   don't have either a count() or isEmpty() method.
+   *
+   * @return bool
+   *   TRUE if session is empty.
+   */
+  public function isEmpty() {
+    $empty = TRUE;
+
+    // @todo: Drupal code is ported to use the session bag instead of direct
+    // $_SESSION super-global usage. Provide solution that only interacts with
+    // Symfony session object.
+    foreach ($_SESSION as $key => $value) {
+      // Ignore SF2 attributes
+      if (0 === strpos($key, '_sf2')) {
+        continue;
+      }
+      $empty = FALSE;
+      break;
+    }
+
+    return $empty && !count($this->getFlashBag()->all()) && !count($this->all());
+  }
+
+  public function save() {
+    // Session saving is checked upper, but avoid accidental save() trigger in
+    // case save is disabled.
+    // @todo May be should throw a \LogicException here?
+    if (!$this->isSaveEnabled()) {
+      return;
+    }
+
+    parent::save();
+  }
+
+  /**
+   * Overrides Symfony\Component\HttpFoundation\Session\Session::migrate().
+   *
+   * Prevent regenerate if saving is disabled.
+   */
+  public function migrate($destroy = FALSE, $lifetime = NULL) {
+
+    if (!$this->isSaveEnabled()) {
+      return;
+    }
+
+    return $this->storage->regenerate($destroy, $lifetime);
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Session/StaticSessionFactory.php b/core/lib/Drupal/Core/Session/StaticSessionFactory.php
new file mode 100644
index 0000000..41efd8c
--- /dev/null
+++ b/core/lib/Drupal/Core/Session/StaticSessionFactory.php
@@ -0,0 +1,44 @@
+<?php
+
+/**
+ * @file
+ * Defines Drupal\Core\Session\StaticSessionFactory.
+ */
+
+namespace Drupal\Core\Session;
+
+use Drupal\Core\Session\Handler\DatabaseSessionHandler;
+use Drupal\Core\Session\Proxy\CookieOverrideProxy;
+use Drupal\Core\Session\Storage\DrupalSessionStorage;
+
+/**
+ * Static session factory that will allow us to use the session as a synthetic
+ * service into the DIC and avoid dual instantiation due to bootstrap container
+ * definition.
+ *
+ */
+class StaticSessionFactory {
+
+  /**
+   * @var \Drupal\Core\Session\Session
+   */
+  static private $session;
+
+  /**
+   * Get global session service.
+   *
+   * @return \Drupal\Core\Session\Session
+   *   Session service.
+   */
+  static public function getSession() {
+    if (null === self::$session) {
+
+      $handler = new CookieOverrideProxy(new DatabaseSessionHandler());
+      $storage = new DrupalSessionStorage(array(), $handler);
+
+      self::$session = new Session($storage);
+    }
+
+    return self::$session;
+  }
+}
diff --git a/core/lib/Drupal/Core/Session/Storage/DrupalSessionStorage.php b/core/lib/Drupal/Core/Session/Storage/DrupalSessionStorage.php
new file mode 100644
index 0000000..528eb8d
--- /dev/null
+++ b/core/lib/Drupal/Core/Session/Storage/DrupalSessionStorage.php
@@ -0,0 +1,63 @@
+<?php
+
+/**
+ * @file
+ * Defines Drupal\Core\Session\Storage\DrupalSessionStorage.
+ */
+
+namespace Drupal\Core\Session\Storage;
+
+use Drupal\Core\Session\Proxy\CookieOverrideProxy;
+
+use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
+
+/**
+ * Default session storage.
+ *
+ * This is a proxy class between the $_SESSION super global and the Session
+ * object bags.
+ */
+class DrupalSessionStorage extends NativeSessionStorage {
+
+  public function __construct(array $options = array(), $handler = null, MetadataBag $metaBag = null) {
+    // In the parent class, the session_register_shutdown() is called. Because
+    // PHP native session will run the close handler in the PHP shutdown hooks,
+    // most Drupal systems our handler relies on will be destructed before this
+    // call. This is the main reason why we need to extend Symfony's component
+    // in order to avoid the native shutdown to run.
+    $this->setMetadataBag($metaBag);
+    $this->setOptions($options);
+    $this->setSaveHandler($handler);
+  }
+
+  public function clear() {
+    parent::clear();
+
+    // Clearing the session is a signal sent when session is invalidated, this
+    // means we can mark the session handler as inactive so it won't attempt
+    // any empty session write. Our session handler will send session cookie at
+    // write time. This allows lazy cookie sending to the client.
+    $this->saveHandler->setActive(FALSE);
+  }
+
+  public function regenerate($destroy = FALSE, $lifetime = NULL) {
+
+    if (null !== $lifetime) {
+      ini_set('session.cookie_lifetime', $lifetime);
+    }
+
+    if ($destroy) {
+      $this->metadataBag->stampNew();
+    }
+
+    // If the current save handler is our own we must rely its own session
+    // identifier generation method. I hope Symfony will move this call to
+    // this object so we can get rid of this method override.
+    if ($this->saveHandler instanceof CookieOverrideProxy) {
+      return $this->saveHandler->regenerateId($destroy);
+    }
+    else {
+      return session_regenerate_id($destroy);
+    }
+  }
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/Session/SessionTest.php b/core/modules/system/lib/Drupal/system/Tests/Session/SessionTest.php
index 02503f7..235ee73 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Session/SessionTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Session/SessionTest.php
@@ -27,6 +27,13 @@ public static function getInfo() {
   }
 
   /**
+   * Test that a DIC based session can be created.
+   */
+  function testDICSession() {
+    $session = drupal_container()->get('session');
+  }
+
+  /**
    * Tests for drupal_save_session() and drupal_session_regenerate().
    */
   function testSessionSaveRegenerate() {
