Skip to content

Commit a02c5e2

Browse files
committed
Allow permanent Set-Cookie
1 parent 3459a69 commit a02c5e2

File tree

2 files changed

+77
-1
lines changed

2 files changed

+77
-1
lines changed

src/Session.php

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ protected function setOptions(array $custom) : void
9696
// used to auto-regenerate the session id:
9797
'auto_regenerate_maxlifetime' => 0,
9898
'auto_regenerate_destroy' => true,
99+
'set_cookie_permanent' => false,
99100
];
100101
if (\PHP_VERSION_ID < 80400) {
101102
$default['sid_bits_per_character'] = 6;
@@ -118,7 +119,8 @@ protected function getOptions(array $custom = []) : array
118119
: $this->options;
119120
unset(
120121
$options['auto_regenerate_maxlifetime'],
121-
$options['auto_regenerate_destroy']
122+
$options['auto_regenerate_destroy'],
123+
$options['set_cookie_permanent'],
122124
);
123125
return $options;
124126
}
@@ -146,6 +148,7 @@ public function start(array $customOptions = []) : bool
146148
);
147149
}
148150
$time = \time();
151+
$this->setPermanentCookie($time);
149152
$this->autoRegenerate($time);
150153
$this->clearTemp($time);
151154
$this->clearFlash();
@@ -169,6 +172,33 @@ public function activate() : bool
169172
return $this->start();
170173
}
171174

175+
/**
176+
* @param int $time
177+
*
178+
* @see https://www.php.net/manual/en/function.session-set-cookie-params.php#100657
179+
* @see https://stackoverflow.com/a/34252812/6027968
180+
*/
181+
protected function setPermanentCookie(int $time) : void
182+
{
183+
$setCookie = (bool) $this->options['set_cookie_permanent'];
184+
if ($setCookie === false) {
185+
return;
186+
}
187+
$params = \session_get_cookie_params();
188+
\setcookie(
189+
\session_name(), // @phpstan-ignore-line
190+
\session_id(), // @phpstan-ignore-line
191+
[ // @phpstan-ignore-line
192+
'expires' => $time + $this->options['cookie_lifetime'],
193+
'path' => $params['path'],
194+
'domain' => $params['domain'],
195+
'secure' => $params['secure'],
196+
'httponly' => $params['httponly'],
197+
'samesite' => $params['samesite'],
198+
]
199+
);
200+
}
201+
172202
/**
173203
* Auto regenerate the session id.
174204
*

tests/TestCase.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,4 +255,50 @@ public function testDestroyCookie() : void
255255
{
256256
self::assertTrue($this->session->destroyCookie());
257257
}
258+
259+
/**
260+
* By default, a Set-Cookie header is set when the session starts.
261+
*
262+
* @see TestCase::testSetCookiePermanent()
263+
*/
264+
public function testSetOneCookie() : void
265+
{
266+
$this->session->stop();
267+
$headers = xdebug_get_headers();
268+
$count = 0;
269+
foreach ($headers as $header) {
270+
if (\str_starts_with($header, 'Set-Cookie: SessionName=')) {
271+
$count++;
272+
}
273+
}
274+
self::assertSame(1, $count);
275+
}
276+
277+
/**
278+
* The first time the session is started with the set_cookie_permanent
279+
* option, two identical Set-Cookie headers are set.
280+
*
281+
* In future requests the Set-Cookie header is set only once if the request
282+
* contains the Cookie header with the session name and a valid value (but
283+
* this could not be tested).
284+
*
285+
* @see TestCase::testSetOneCookie()
286+
*/
287+
public function testSetCookiePermanent() : void
288+
{
289+
$this->session->stop();
290+
$this->session = new Session([
291+
'name' => 'sess_id',
292+
'set_cookie_permanent' => 1,
293+
], $this->handler);
294+
$this->session->start();
295+
$headers = xdebug_get_headers();
296+
$count = 0;
297+
foreach ($headers as $header) {
298+
if (\str_starts_with($header, 'Set-Cookie: sess_id=')) {
299+
$count++;
300+
}
301+
}
302+
self::assertSame(2, $count);
303+
}
258304
}

0 commit comments

Comments
 (0)