Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit b0aef93

Browse filesBrowse files
committed
Do not send deleted session cookie twice in the response
1 parent 91b7bdd commit b0aef93
Copy full SHA for b0aef93

File tree

4 files changed

+78
-1
lines changed
Filter options

4 files changed

+78
-1
lines changed

‎src/Symfony/Component/HttpFoundation/Session/SessionUtils.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpFoundation/Session/SessionUtils.php
+5-1Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ public static function popSessionCookie(string $sessionName, string $sessionId):
3030
$sessionCookie = null;
3131
$sessionCookiePrefix = sprintf(' %s=', urlencode($sessionName));
3232
$sessionCookieWithId = sprintf('%s%s;', $sessionCookiePrefix, urlencode($sessionId));
33+
// PHP internally sets the session cookie value to "deleted" when setcookie() is called with empty string $value argument
34+
// which happens in \Symfony\Component\HttpFoundation\Session\Storage\Handler\AbstractSessionHandler::destroy
35+
// when the session gets invalidated (for example on logout) so we must handle this case here too
36+
$sessionCookieWithDeletedId = sprintf('%s%s;', $sessionCookiePrefix, 'deleted');
3337
$otherCookies = [];
3438
foreach (headers_list() as $h) {
3539
if (0 !== stripos($h, 'Set-Cookie:')) {
@@ -38,7 +42,7 @@ public static function popSessionCookie(string $sessionName, string $sessionId):
3842
if (11 === strpos($h, $sessionCookiePrefix, 11)) {
3943
$sessionCookie = $h;
4044

41-
if (11 !== strpos($h, $sessionCookieWithId, 11)) {
45+
if (11 !== strpos($h, $sessionCookieWithId, 11) && 11 !== strpos($h, $sessionCookieWithDeletedId, 11)) {
4246
$otherCookies[] = $h;
4347
}
4448
} else {
+11Lines 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
+60Lines 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

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpFoundation/composer.json
+2Lines 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|^6.0",
2729
"symfony/mime": "^4.4|^5.0|^6.0",
2830
"symfony/expression-language": "^4.4|^5.0|^6.0"
2931
},

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.