test: Testsuite fuer Kernlogik, QR-Codes, Domains und Sicherheit
232 Tests, unter anderem: - Slug-Erzeugung, Kollisionsbehandlung und Validierung - URL-Validierung inklusive IDN, Prozentkodierung und abgelehnter Protokolle; Punycode gegengeprueft gegen idn_to_ascii - QR-Erzeugung in allen Groessen, mit Logo und Level-H-Automatik - Weiterleitung gegen eine echte SQLite-Datenbank samt Domain- Aufloesung ueber den Host-Header - Update einer bestehenden Installation auf mehrere Domains - Angriffsseitig: gefaelschte Proxy-Header, Host-Header-Injektion, SVG mit Skripten, XXE und externen Referenzen
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests;
|
||||
|
||||
use App\Support\CheckToken;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class CheckTokenTest extends TestCase
|
||||
{
|
||||
private const SECRET = 'a4f1c0d2e3b4a5968778695a4b3c2d1e0f1a2b3c4d5e6f708192a3b4c5d6e7f8';
|
||||
|
||||
public function testFreshTokenIsAccepted(): void
|
||||
{
|
||||
$token = CheckToken::create(self::SECRET);
|
||||
|
||||
self::assertTrue(CheckToken::isValid($token, self::SECRET));
|
||||
}
|
||||
|
||||
public function testTokenOfAnotherInstallationIsRejected(): void
|
||||
{
|
||||
// Genau das beweist die Pruefung: nur wer das Geheimnis kennt,
|
||||
// kann ein gueltiges Token erzeugen.
|
||||
$token = CheckToken::create('ein-anderes-geheimnis');
|
||||
|
||||
self::assertFalse(CheckToken::isValid($token, self::SECRET));
|
||||
}
|
||||
|
||||
public function testExpiredTokenIsRejected(): void
|
||||
{
|
||||
$now = 1_800_000_000;
|
||||
$token = CheckToken::create(self::SECRET, $now);
|
||||
|
||||
self::assertTrue(CheckToken::isValid($token, self::SECRET, $now + CheckToken::LIFETIME - 1));
|
||||
self::assertFalse(CheckToken::isValid($token, self::SECRET, $now + CheckToken::LIFETIME + 1));
|
||||
}
|
||||
|
||||
public function testTokenFromTheFutureIsRejected(): void
|
||||
{
|
||||
$now = 1_800_000_000;
|
||||
$token = CheckToken::create(self::SECRET, $now + 3600);
|
||||
|
||||
self::assertFalse(CheckToken::isValid($token, self::SECRET, $now));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string,array{0:string}>
|
||||
*/
|
||||
public static function malformedProvider(): array
|
||||
{
|
||||
return [
|
||||
'leer' => [''],
|
||||
'ohne Punkt' => ['1800000000'],
|
||||
'ohne Signatur' => ['1800000000.'],
|
||||
'Text statt Zeitstempel' => ['abc.def'],
|
||||
'nur Signatur' => ['.abcdef'],
|
||||
'negativer Zeitstempel' => ['-100.abcdef'],
|
||||
'zu viele Teile' => ['1800000000.abc.def'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider malformedProvider
|
||||
*/
|
||||
public function testMalformedTokensAreRejected(string $token): void
|
||||
{
|
||||
self::assertFalse(CheckToken::isValid($token, self::SECRET));
|
||||
}
|
||||
|
||||
public function testSignatureIsNotGuessable(): void
|
||||
{
|
||||
$now = 1_800_000_000;
|
||||
$valid = CheckToken::create(self::SECRET, $now);
|
||||
|
||||
// Signatur um ein Zeichen veraendert.
|
||||
$tampered = substr($valid, 0, -1) . (str_ends_with($valid, 'a') ? 'b' : 'a');
|
||||
|
||||
self::assertNotSame($valid, $tampered);
|
||||
self::assertFalse(CheckToken::isValid($tampered, self::SECRET, $now));
|
||||
}
|
||||
|
||||
public function testTokenContainsNoSecret(): void
|
||||
{
|
||||
$token = CheckToken::create(self::SECRET);
|
||||
|
||||
self::assertStringNotContainsString(self::SECRET, $token);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user