[Server] Restrict FileSessionStore::gc() to owned session files (#479)
This commit is contained in:
parent
d59950f1ac
commit
c36e805086
2 changed files with 28 additions and 5 deletions
|
|
@ -128,6 +128,11 @@ class FileSessionStore implements SessionStoreInterface
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only delete files this store owns: sessions are named by their RFC 4122 UUID
|
||||||
|
if (!Uuid::isValid($entry)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
$path = $this->directory.\DIRECTORY_SEPARATOR.$entry;
|
$path = $this->directory.\DIRECTORY_SEPARATOR.$entry;
|
||||||
if (!is_file($path)) {
|
if (!is_file($path)) {
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -136,11 +141,7 @@ class FileSessionStore implements SessionStoreInterface
|
||||||
$mtime = @filemtime($path) ?: 0;
|
$mtime = @filemtime($path) ?: 0;
|
||||||
if (($now - $mtime) > $this->ttl) {
|
if (($now - $mtime) > $this->ttl) {
|
||||||
@unlink($path);
|
@unlink($path);
|
||||||
try {
|
$deleted[] = Uuid::fromString($entry);
|
||||||
$deleted[] = Uuid::fromString($entry);
|
|
||||||
} catch (\Throwable) {
|
|
||||||
// ignore non-UUID file names
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,28 @@ class FileSessionStoreTest extends TestCase
|
||||||
$this->assertSame('payload', $store->read($id));
|
$this->assertSame('payload', $store->read($id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[TestDox('gc() only deletes expired session files, never foreign files in the directory')]
|
||||||
|
public function testGcLeavesForeignFilesAlone(): void
|
||||||
|
{
|
||||||
|
$store = new FileSessionStore($this->directory, ttl: 60);
|
||||||
|
$id = new UuidV4();
|
||||||
|
$store->write($id, 'payload');
|
||||||
|
|
||||||
|
$foreign = $this->directory.'/important.lock';
|
||||||
|
file_put_contents($foreign, 'not a session');
|
||||||
|
|
||||||
|
// Make everything stale
|
||||||
|
$expired = time() - 120;
|
||||||
|
touch($this->directory.'/'.$id->toRfc4122(), $expired);
|
||||||
|
touch($foreign, $expired);
|
||||||
|
|
||||||
|
$deleted = $store->gc();
|
||||||
|
|
||||||
|
$this->assertEquals([$id], $deleted);
|
||||||
|
$this->assertFileDoesNotExist($this->directory.'/'.$id->toRfc4122());
|
||||||
|
$this->assertFileExists($foreign);
|
||||||
|
}
|
||||||
|
|
||||||
#[TestDox('rejects an unwritable directory with the SDK\'s own exception')]
|
#[TestDox('rejects an unwritable directory with the SDK\'s own exception')]
|
||||||
public function testUnwritableDirectoryThrowsPackageException(): void
|
public function testUnwritableDirectoryThrowsPackageException(): void
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue