From 8e98edcddea5e5b8e70834cf7174837276d839d3 Mon Sep 17 00:00:00 2001 From: Trent Steel Date: Fri, 11 Feb 2022 13:57:34 +1000 Subject: [PATCH] [HttpKernel] Use the existing session id if available. --- .../EventListener/AbstractSessionListener.php | 20 +++++----- .../EventListener/SessionListenerTest.php | 38 ++++++++++++++++++- 2 files changed, 46 insertions(+), 12 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/EventListener/AbstractSessionListener.php b/src/Symfony/Component/HttpKernel/EventListener/AbstractSessionListener.php index 7c0c1aee3ac17..2e8f0e2869be1 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/AbstractSessionListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/AbstractSessionListener.php @@ -72,17 +72,17 @@ public function onKernelRequest(RequestEvent $event) $request->setSessionFactory(function () use (&$sess, $request) { if (!$sess) { $sess = $this->getSession(); - } - /* - * For supporting sessions in php runtime with runners like roadrunner or swoole, the session - * cookie needs to be read from the cookie bag and set on the session storage. - * - * Do not set it when a native php session is active. - */ - if ($sess && !$sess->isStarted() && \PHP_SESSION_ACTIVE !== session_status()) { - $sessionId = $request->cookies->get($sess->getName(), ''); - $sess->setId($sessionId); + /* + * For supporting sessions in php runtime with runners like roadrunner or swoole, the session + * cookie needs to be read from the cookie bag and set on the session storage. + * + * Do not set it when a native php session is active. + */ + if ($sess && !$sess->isStarted() && \PHP_SESSION_ACTIVE !== session_status()) { + $sessionId = $sess->getId() ?: $request->cookies->get($sess->getName(), ''); + $sess->setId($sessionId); + } } return $sess; diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/SessionListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/SessionListenerTest.php index ca49b42d41673..f0609316b4943 100644 --- a/src/Symfony/Component/HttpKernel/Tests/EventListener/SessionListenerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/EventListener/SessionListenerTest.php @@ -202,6 +202,40 @@ public function testSessionCookieNotWrittenCookieGiven() $this->assertCount(0, $cookies); } + /** + * @runInSeparateProcess + */ + public function testNewSessionIdIsNotOverwritten() + { + $newSessionId = $this->createValidSessionId(); + + $this->assertNotEmpty($newSessionId); + + $request = new Request(); + $request->cookies->set('PHPSESSID', 'OLD-SESSION-ID'); + + $listener = $this->createListener($request, new NativeSessionStorageFactory()); + + $kernel = $this->createMock(HttpKernelInterface::class); + $listener->onKernelRequest(new RequestEvent($kernel, $request, HttpKernelInterface::MAIN_REQUEST)); + + $session = $request->getSession(); + $this->assertSame($newSessionId, $session->getId()); + $session->set('hello', 'world'); + + $response = new Response(); + $listener->onKernelResponse(new ResponseEvent($kernel, $request, HttpKernelInterface::MAIN_REQUEST, $response)); + $this->assertSame($newSessionId, $session->getId()); + + $cookies = $response->headers->getCookies(); + + $this->assertCount(1, $cookies); + $sessionCookie = $cookies[0]; + + $this->assertSame('PHPSESSID', $sessionCookie->getName()); + $this->assertSame($newSessionId, $sessionCookie->getValue()); + } + /** * @runInSeparateProcess */ @@ -488,7 +522,7 @@ public function testUninitializedSessionWithoutInitializedSession() public function testSurrogateMainRequestIsPublic() { $session = $this->createMock(Session::class); - $session->expects($this->exactly(2))->method('getName')->willReturn('PHPSESSID'); + $session->expects($this->exactly(1))->method('getName')->willReturn('PHPSESSID'); $session->expects($this->exactly(4))->method('getUsageIndex')->will($this->onConsecutiveCalls(0, 1, 1, 1)); $container = new Container(); @@ -528,7 +562,7 @@ public function testSurrogateMainRequestIsPublic() public function testGetSessionIsCalledOnce() { $session = $this->createMock(Session::class); - $session->expects($this->exactly(2))->method('getName')->willReturn('PHPSESSID'); + $session->expects($this->exactly(1))->method('getName')->willReturn('PHPSESSID'); $sessionStorage = $this->createMock(NativeSessionStorage::class); $kernel = $this->createMock(KernelInterface::class);