Commit 304d50a7 authored by alexpott's avatar alexpott

Issue #2330279 by znerol: Fixed When operating in mixed mode SSL: data from...

Issue #2330279 by znerol: Fixed When operating in mixed mode SSL: data from anonymous non-HTTP session is still available after login.
parent a782ad53
......@@ -40,6 +40,13 @@ class SessionHandler extends AbstractProxy implements \SessionHandlerInterface {
*/
protected $connection;
/**
* An associative array of obsolete sessions with session id as key, and db-key as value.
*
* @var array
*/
protected $obsoleteSessionIds = array();
/**
* Constructs a new SessionHandler instance.
*
......@@ -94,9 +101,12 @@ public function read($sid) {
// Fallback and try to load the anonymous non-HTTPS session. Use the
// non-HTTPS session id as the key.
if ($cookies->has($insecure_session_name)) {
$values = $this->connection->query("SELECT u.*, s.* FROM {users_field_data} u INNER JOIN {sessions} s ON u.uid = s.uid WHERE u.default_langcode = 1 AND s.sid = :sid AND s.uid = 0", array(
':sid' => Crypt::hashBase64($cookies->get($insecure_session_name)),
))->fetchAssoc();
$insecure_session_id = $cookies->get($insecure_session_name);
$args = array(':sid' => Crypt::hashBase64($insecure_session_id));
$values = $this->connection->query("SELECT u.*, s.* FROM {users_field_data} u INNER JOIN {sessions} s ON u.uid = s.uid WHERE u.default_langcode = 1 AND s.sid = :sid AND s.uid = 0", $args)->fetchAssoc();
if ($values) {
$this->sessionSetObsolete($insecure_session_id);
}
}
}
}
......@@ -181,6 +191,9 @@ public function write($sid, $value) {
->fields($fields)
->execute();
// Remove obsolete sessions.
$this->cleanupObsoleteSessions();
// Likewise, do not update access time more than once per 180 seconds.
if ($user->isAuthenticated() && REQUEST_TIME - $user->getLastAccessedTime() > Settings::get('session_write_interval', 180)) {
/** @var \Drupal\user\UserStorageInterface $storage */
......@@ -237,6 +250,10 @@ public function destroy($sid) {
elseif ($this->sessionManager->isMixedMode()) {
$this->deleteCookie('S' . $this->getName(), TRUE);
}
// Remove obsolete sessions.
$this->cleanupObsoleteSessions();
return TRUE;
}
......@@ -275,4 +292,22 @@ protected function deleteCookie($name, $secure = NULL) {
}
}
/**
* Mark a session for garbage collection upon session save.
*/
protected function sessionSetObsolete($sid, $https = FALSE) {
$this->obsoleteSessionIds[$sid] = $https ? 'ssid' : 'sid';
}
/**
* Remove sessions marked for garbage collection.
*/
protected function cleanupObsoleteSessions() {
foreach ($this->obsoleteSessionIds as $sid => $key) {
$this->connection->delete('sessions')
->condition($key, Crypt::hashBase64($sid))
->execute();
}
}
}
......@@ -241,9 +241,6 @@ public function regenerate($destroy = FALSE, $lifetime = NULL) {
if ($is_https && $this->isMixedMode()) {
$insecure_session_name = $this->getInsecureName();
if ($this->isStarted() && $cookies->has($insecure_session_name)) {
$old_insecure_session_id = $cookies->get($insecure_session_name);
}
$params = session_get_cookie_params();
$session_id = Crypt::randomBytesBase64();
// If a session cookie lifetime is set, the session will expire
......@@ -279,16 +276,8 @@ public function regenerate($destroy = FALSE, $lifetime = NULL) {
->condition($is_https ? 'ssid' : 'sid', Crypt::hashBase64($old_session_id))
->execute();
}
elseif (isset($old_insecure_session_id)) {
// If logging in to the secure site, and there was no active session on
// the secure site but a session was active on the insecure site, update
// the insecure session with the new session identifiers.
$this->connection->update('sessions')
->fields(array('sid' => Crypt::hashBase64($session_id), 'ssid' => Crypt::hashBase64($this->getId())))
->condition('sid', Crypt::hashBase64($old_insecure_session_id))
->execute();
}
else {
if (!$this->isStarted()) {
// Start the session when it doesn't exist yet.
// Preserve the logged in user, as it will be reset to anonymous
// by \Drupal\Core\Session\SessionHandler::read().
......
......@@ -200,7 +200,7 @@ protected function testMixedModeSslSession() {
// Test that session data saved before login is not available using the
// pre-login anonymous cookie.
$this->cookies = array();
$this->drupalGet('session-test/get', array('Cookie: ' . $anonymous_cookie));
$this->drupalGet('session-test/get', array(), array('Cookie: ' . $anonymous_cookie));
$this->assertNoText($session_data, 'Initial anonymous session is inactive after login.');
// Clear browser cookie jar.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment