production/Framework/Csrf.php
2026-04-18 22:19:22 +00:00

63 lines
1.8 KiB
PHP
Executable File

<?php
class Csrf
{
private const EXPIRATION = 3600; // 1 heure en secondes
/**
* Génère UN seul token pour toute la session
*/
public static function generateToken(): string {
// Régénère si absent OU expiré
if (empty($_SESSION['csrf_token']) || self::isExpired()) {
$_SESSION['csrf_token'] = [
'value' => bin2hex(random_bytes(32)),
'created_at' => time(),
];
}
return $_SESSION['csrf_token']['value'];
}
/**
* Vérifie si le token a expiré
*/
private static function isExpired(): bool {
$createdAt = $_SESSION['csrf_token']['created_at'] ?? 0;
return (time() - $createdAt) > self::EXPIRATION;
}
/**
* Valide le token soumis
*/
public static function validateToken(string $submittedToken): bool {
// Rejeté si la session ne contient pas de token
if (empty($_SESSION['csrf_token'])) return false;
// Rejeté si expiré
if (self::isExpired()) {
self::regenerate();
return false;
}
// Comparaison sécurisée (résistante aux attaques par timing)
return hash_equals($_SESSION['csrf_token']['value'], $submittedToken);
}
/**
* Champ HTML à insérer dans les formulaires
*/
public static function field(): string {
$token = self::generateToken();
// return '<input type="hidden" name="csrf_token" value="' . htmlspecialchars($token) . '">';
}
/**
* Régénère le token (déconnexion, ou expiration)
*/
public static function regenerate(): void {
$_SESSION['csrf_token'] = [
'value' => bin2hex(random_bytes(32)),
'created_at' => time(),
];
}
}