X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2Fsession%2FSessionBackend.php;h=1e2b476baff3980e1ff5e32c7c7f792e7a2f8cc4;hb=3aa24e7c4b4374007958eee4fed6c2312fb9233a;hp=fe446e356b57d7f5c70fdd180972bb14734f8808;hpb=bc86ab6eb2992f178d4f970c81c44c0505239678;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/session/SessionBackend.php b/includes/session/SessionBackend.php index fe446e356b..1e2b476baf 100644 --- a/includes/session/SessionBackend.php +++ b/includes/session/SessionBackend.php @@ -79,7 +79,7 @@ final class SessionBackend { private $curIndex = 0; /** @var WebRequest[] Session requests */ - private $requests = array(); + private $requests = []; /** @var SessionProvider provider */ private $provider; @@ -135,14 +135,14 @@ final class SessionBackend { !isset( $blob['metadata'] ) || !is_array( $blob['metadata'] ) || !isset( $blob['data'] ) || !is_array( $blob['data'] ) ) { - $this->data = array(); + $this->data = []; $this->dataDirty = true; $this->metaDirty = true; $this->logger->debug( 'SessionBackend "{session}" is unsaved, marking dirty in constructor', - array( + [ 'session' => $this->id, - ) ); + ] ); } else { $this->data = $blob['data']; if ( isset( $blob['metadata']['loggedOut'] ) ) { @@ -154,9 +154,9 @@ final class SessionBackend { $this->metaDirty = true; $this->logger->debug( 'SessionBackend "{session}" metadata dirty due to missing expiration timestamp', - array( + [ 'session' => $this->id, - ) ); + ] ); } } $this->dataHash = md5( serialize( $this->data ) ); @@ -170,7 +170,7 @@ final class SessionBackend { public function getSession( WebRequest $request ) { $index = ++$this->curIndex; $this->requests[$index] = $request; - $session = new Session( $this, $index ); + $session = new Session( $this, $index, $this->logger ); return $session; } @@ -225,10 +225,10 @@ final class SessionBackend { $this->metaDirty = true; $this->logger->debug( 'SessionBackend "{session}" metadata dirty due to ID reset (formerly "{oldId}")', - array( + [ 'session' => $this->id, 'oldId' => $oldId, - ) ); + ] ); if ( $restart ) { session_id( (string)$this->id ); @@ -274,15 +274,44 @@ final class SessionBackend { $this->metaDirty = true; $this->logger->debug( 'SessionBackend "{session}" force-persist due to persist()', - array( + [ 'session' => $this->id, - ) ); + ] ); $this->autosave(); } else { $this->renew(); } } + /** + * Make this session not persisted across requests + */ + public function unpersist() { + if ( $this->persist ) { + // Close the PHP session, if we're the one that's open + if ( $this->usePhpSessionHandling && PHPSessionHandler::isEnabled() && + session_id() === (string)$this->id + ) { + $this->logger->debug( + 'SessionBackend "{session}" Closing PHP session for unpersist', + [ 'session' => $this->id ] + ); + session_write_close(); + session_id( '' ); + } + + $this->persist = false; + $this->forcePersist = true; + $this->metaDirty = true; + + // Delete the session data, so the local cache-only write in + // self::save() doesn't get things out of sync with the backend. + $this->store->delete( wfMemcKey( 'MWSession', (string)$this->id ) ); + + $this->autosave(); + } + } + /** * Indicate whether the user should be remembered independently of the * session ID. @@ -303,9 +332,9 @@ final class SessionBackend { $this->metaDirty = true; $this->logger->debug( 'SessionBackend "{session}" metadata dirty due to remember-user change', - array( + [ 'session' => $this->id, - ) ); + ] ); $this->autosave(); } } @@ -364,9 +393,9 @@ final class SessionBackend { $this->metaDirty = true; $this->logger->debug( 'SessionBackend "{session}" metadata dirty due to user change', - array( + [ 'session' => $this->id, - ) ); + ] ); $this->autosave(); } @@ -400,9 +429,9 @@ final class SessionBackend { $this->metaDirty = true; $this->logger->debug( 'SessionBackend "{session}" metadata dirty due to force-HTTPS change', - array( + [ 'session' => $this->id, - ) ); + ] ); $this->autosave(); } } @@ -426,9 +455,9 @@ final class SessionBackend { $this->metaDirty = true; $this->logger->debug( 'SessionBackend "{session}" metadata dirty due to logged-out-timestamp change', - array( + [ 'session' => $this->id, - ) ); + ] ); $this->autosave(); } } @@ -456,9 +485,9 @@ final class SessionBackend { $this->metaDirty = true; $this->logger->debug( 'SessionBackend "{session}" metadata dirty due to provider metadata change', - array( + [ 'session' => $this->id, - ) ); + ] ); $this->autosave(); } } @@ -491,10 +520,10 @@ final class SessionBackend { $this->dataDirty = true; $this->logger->debug( 'SessionBackend "{session}" data dirty due to addData(): {callers}', - array( + [ 'session' => $this->id, 'callers' => wfGetAllCallers( 5 ), - ) ); + ] ); } } } @@ -507,10 +536,10 @@ final class SessionBackend { $this->dataDirty = true; $this->logger->debug( 'SessionBackend "{session}" data dirty due to dirty(): {callers}', - array( + [ 'session' => $this->id, 'callers' => wfGetAllCallers( 5 ), - ) ); + ] ); } /** @@ -524,18 +553,18 @@ final class SessionBackend { $this->metaDirty = true; $this->logger->debug( 'SessionBackend "{callers}" metadata dirty for renew(): {callers}', - array( + [ 'session' => $this->id, 'callers' => wfGetAllCallers( 5 ), - ) ); + ] ); if ( $this->persist ) { $this->forcePersist = true; $this->logger->debug( 'SessionBackend "{session}" force-persist for renew(): {callers}', - array( + [ 'session' => $this->id, 'callers' => wfGetAllCallers( 5 ), - ) ); + ] ); } } $this->autosave(); @@ -572,27 +601,28 @@ final class SessionBackend { * @param bool $closing Whether the session is being closed */ public function save( $closing = false ) { - if ( $this->provider->getManager()->isUserSessionPrevented( $this->user->getName() ) ) { + $anon = $this->user->isAnon(); + + if ( !$anon && $this->provider->getManager()->isUserSessionPrevented( $this->user->getName() ) ) { $this->logger->debug( 'SessionBackend "{session}" not saving, user {user} was ' . 'passed to SessionManager::preventSessionsForUser', - array( + [ 'session' => $this->id, 'user' => $this->user, - ) ); + ] ); return; } // Ensure the user has a token // @codeCoverageIgnoreStart - $anon = $this->user->isAnon(); if ( !$anon && !$this->user->getToken( false ) ) { $this->logger->debug( 'SessionBackend "{session}" creating token for user {user} on save', - array( + [ 'session' => $this->id, 'user' => $this->user, - ) ); + ] ); $this->user->setToken(); if ( !wfReadOnly() ) { $this->user->saveSettings(); @@ -606,11 +636,11 @@ final class SessionBackend { ) { $this->logger->debug( 'SessionBackend "{session}" data dirty due to hash mismatch, {expected} !== {got}', - array( + [ 'session' => $this->id, 'expected' => $this->dataHash, 'got' => md5( serialize( $this->data ) ), - ) ); + ] ); $this->dataDirty = true; } @@ -621,21 +651,29 @@ final class SessionBackend { $this->logger->debug( 'SessionBackend "{session}" save: dataDirty={dataDirty} ' . 'metaDirty={metaDirty} forcePersist={forcePersist}', - array( + [ 'session' => $this->id, 'dataDirty' => (int)$this->dataDirty, 'metaDirty' => (int)$this->metaDirty, 'forcePersist' => (int)$this->forcePersist, - ) ); + ] ); - // Persist to the provider, if flagged - if ( $this->persist && ( $this->metaDirty || $this->forcePersist ) ) { - foreach ( $this->requests as $request ) { - $request->setSessionId( $this->getSessionId() ); - $this->provider->persistSession( $this, $request ); - } - if ( !$closing ) { - $this->checkPHPSession(); + // Persist or unpersist to the provider, if necessary + if ( $this->metaDirty || $this->forcePersist ) { + if ( $this->persist ) { + foreach ( $this->requests as $request ) { + $request->setSessionId( $this->getSessionId() ); + $this->provider->persistSession( $this, $request ); + } + if ( !$closing ) { + $this->checkPHPSession(); + } + } else { + foreach ( $this->requests as $request ) { + if ( $request->getSessionId() === $this->id ) { + $this->provider->unpersistSession( $request ); + } + } } } @@ -646,7 +684,7 @@ final class SessionBackend { } // Save session data to store, if necessary - $metadata = $origMetadata = array( + $metadata = $origMetadata = [ 'provider' => (string)$this->provider, 'providerMetadata' => $this->providerMetadata, 'userId' => $anon ? 0 : $this->user->getId(), @@ -657,9 +695,9 @@ final class SessionBackend { 'expires' => time() + $this->lifetime, 'loggedOut' => $this->loggedOut, 'persisted' => $this->persist, - ); + ]; - \Hooks::run( 'SessionMetadata', array( $this, &$metadata, $this->requests ) ); + \Hooks::run( 'SessionMetadata', [ $this, &$metadata, $this->requests ] ); foreach ( $origMetadata as $k => $v ) { if ( $metadata[$k] !== $v ) { @@ -669,10 +707,10 @@ final class SessionBackend { $this->store->set( wfMemcKey( 'MWSession', (string)$this->id ), - array( + [ 'data' => $this->data, 'metadata' => $metadata, - ), + ], $metadata['expires'], $this->persist ? 0 : CachedBagOStuff::WRITE_CACHE_ONLY ); @@ -699,9 +737,9 @@ final class SessionBackend { ) { $this->logger->debug( 'SessionBackend "{session}" Taking over PHP session', - array( + [ 'session' => $this->id, - ) ); + ] ); session_id( (string)$this->id ); \MediaWiki\quietCall( 'session_start' ); }