Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b08025d

Browse files
committed
Do not send deleted session cookie twice in the response
1 parent 91b7bdd commit b08025d

File tree

4 files changed

+78
-0
lines changed

4 files changed

+78
-0
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
2+
Array
3+
(
4+
[0] => Content-Type: text/plain; charset=utf-8
5+
[1] => Cache-Control: max-age=0, private, must-revalidate
6+
[2] => Cache-Control: max-age=0, must-revalidate, private
7+
[3] => Date: Sat, 12 Nov 1955 20:04:00 GMT
8+
[4] => Expires: %s, %d %s %d %d:%d:%d GMT
9+
[5] => Set-Cookie: PHPSESSID=deleted; expires=%s, %d-%s-%d %d:%d:%d GMT; Max-Age=%d; %s
10+
)
11+
shutdown
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
use Symfony\Component\DependencyInjection\Container;
4+
use Symfony\Component\HttpFoundation\Request;
5+
use Symfony\Component\HttpFoundation\RequestStack;
6+
use Symfony\Component\HttpFoundation\Response;
7+
use Symfony\Component\HttpFoundation\Session\SessionFactory;
8+
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorageFactory;
9+
use Symfony\Component\HttpKernel\Event\RequestEvent;
10+
use Symfony\Component\HttpKernel\Event\ResponseEvent;
11+
use Symfony\Component\HttpKernel\EventListener\SessionListener;
12+
use Symfony\Component\HttpKernel\HttpKernelInterface;
13+
14+
/** @var Response $r */
15+
$r = require __DIR__.'/common.inc';
16+
17+
$sessionId = 'vqd4dpbtst3af0k4sdl18nebkn';
18+
session_id($sessionId);
19+
$sessionName = session_name();
20+
$_COOKIE[$sessionName] = $sessionId;
21+
22+
$request = new Request();
23+
$request->cookies->set($sessionName, $sessionId);
24+
25+
$requestStack = new RequestStack();
26+
$requestStack->push($request);
27+
28+
$sessionFactory = new SessionFactory($requestStack, new NativeSessionStorageFactory());
29+
30+
$container = new Container();
31+
$container->set('request_stack', $requestStack);
32+
$container->set('session_factory', $sessionFactory);
33+
34+
$listener = new SessionListener($container);
35+
36+
$kernel = new class($r) implements HttpKernelInterface {
37+
/**
38+
* @var Response
39+
*/
40+
private $response;
41+
42+
public function __construct(Response $response)
43+
{
44+
$this->response = $response;
45+
}
46+
47+
public function handle(Request $request, int $type = self::MAIN_REQUEST, bool $catch = true): Response
48+
{
49+
return $this->response;
50+
}
51+
};
52+
53+
$listener->onKernelRequest(new RequestEvent($kernel, $request, HttpKernelInterface::MAIN_REQUEST));
54+
$session = $request->getSession();
55+
$session->set('foo', 'bar');
56+
$session->invalidate();
57+
58+
$listener->onKernelResponse(new ResponseEvent($kernel, $request, HttpKernelInterface::MAIN_REQUEST, $r));
59+
60+
$r->sendHeaders();

src/Symfony/Component/HttpFoundation/composer.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
"require-dev": {
2525
"predis/predis": "~1.0",
2626
"symfony/cache": "^4.4|^5.0|^6.0",
27+
"symfony/dependency-injection": "^5.4|^6.0",
28+
"symfony/http-kernel": "^5.4.12|^6.1.4",
2729
"symfony/mime": "^4.4|^5.0|^6.0",
2830
"symfony/expression-language": "^4.4|^5.0|^6.0"
2931
},

src/Symfony/Component/HttpKernel/EventListener/AbstractSessionListener.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,11 @@ public function onKernelResponse(ResponseEvent $event)
158158

159159
$isSessionEmpty = $session->isEmpty() && empty($_SESSION); // checking $_SESSION to keep compatibility with native sessions
160160
if ($requestSessionCookieId && $isSessionEmpty) {
161+
// PHP internally sets the session cookie value to "deleted" when setcookie() is called with empty string $value argument
162+
// which happens in \Symfony\Component\HttpFoundation\Session\Storage\Handler\AbstractSessionHandler::destroy
163+
// when the session gets invalidated (for example on logout) so we must handle this case here too
164+
// otherwise we would send two Set-Cookie headers back with the response
165+
SessionUtils::popSessionCookie($sessionName, 'deleted');
161166
$response->headers->clearCookie(
162167
$sessionName,
163168
$sessionCookiePath,

0 commit comments

Comments
 (0)