From 8c663379dcb9859a060e07681cc9082c025cf203 Mon Sep 17 00:00:00 2001 From: polo Date: Thu, 22 May 2025 16:59:25 +0200 Subject: classe Captcha --- public/index.php | 26 +++++++++---------- src/controller/Captcha.php | 52 +++++++++++++++++++++++++++++++++++++ src/controller/password.php | 62 ++++++++++++--------------------------------- src/view/password.php | 17 +++++++------ 4 files changed, 90 insertions(+), 67 deletions(-) create mode 100644 src/controller/Captcha.php diff --git a/public/index.php b/public/index.php index aa080c4..170c23d 100644 --- a/public/index.php +++ b/public/index.php @@ -3,7 +3,9 @@ declare(strict_types=1); -// -- prétraitement -- + +/* -- partie 1: prétraitement -- */ + // une nouvelle classe? taper: composer dump-autoload -o require "../vendor/autoload.php"; @@ -31,17 +33,15 @@ $_SESSION['admin'] = !isset($_SESSION['admin']) ? false : $_SESSION['admin']; // // login, mot de passe et captcha require '../src/controller/password.php'; -existUsers($entityManager); +existUsers($entityManager); // si la table user est vide, on en crée un -// -- navigation avec les GET -- -$current_page = 'accueil'; -if(!empty($_GET['page'])) -{ - $current_page = htmlspecialchars($_GET['page']); -} -define('CURRENT_PAGE', $current_page); -// -- traitement des POST (formulaires et AJAX) -- +/* -- partie 2: affichage d'une page ou traitement d'un POST -- */ + +// navigation avec les GET +define('CURRENT_PAGE', !empty($_GET['page']) ? htmlspecialchars($_GET['page']) : 'accueil'); + +// traitement des POST (formulaires et AJAX) require '../src/controller/post.php'; // id des articles @@ -67,11 +67,11 @@ elseif($_SESSION['admin'] && isset($_GET['page']) && isset($_GET['action']) && $ MainBuilder::$modif_mode = true; } -// -- contrôleurs -- +// contrôleur principal $director = new Director($entityManager, true); $director->makeRootNode($id); $node = $director->getNode(); -// -- vues -- +// vues $view_builder = new ViewBuilder($node); -echo $view_builder->render(); // et voilà! +echo $view_builder->render(); // et voilà! \ No newline at end of file diff --git a/src/controller/Captcha.php b/src/controller/Captcha.php new file mode 100644 index 0000000..3253b95 --- /dev/null +++ b/src/controller/Captcha.php @@ -0,0 +1,52 @@ +a = rand(2, 9); + $this->b = rand(2, 9); + $this->solution = $this->a * $this->b; + } + + public function getA(): string + { + return $this->toLettersFrench($this->a); + } + public function getB(): string + { + return $this->toLettersFrench($this->b); + } + public function getSolution(): int + { + return $this->solution; + } + + private function toLettersFrench(int $number): string + { + return match($number){ + 2 => 'deux', + 3 => 'trois', + 4 => 'quatre', + 5 => 'cinq', + 6 => 'six', + 7 => 'sept', + 8 => 'huit', + 9 => 'neuf', + default => '', // erreur + }; + } + static public function controlInput(string $input = '0'): int + { + // un POST est une chaîne qu'on doit convertir en nombre si: + // test de format: $input est un nombre + // test d'intégrité: supprimer les décimales avec (int) ne change pas la valeur du nombre + return is_numeric($input) && $input == (int)$input ? (int)$input : 0; + } +} \ No newline at end of file diff --git a/src/controller/password.php b/src/controller/password.php index 4748d9d..4b387ca 100644 --- a/src/controller/password.php +++ b/src/controller/password.php @@ -31,18 +31,18 @@ function createPassword(EntityManager $entityManager) { // fonction exécutée à priori deux fois d'affilée: affichage puis traitement de la saisie - // II - traitement unset($_SESSION['user']); $captcha_solution = (isset($_SESSION['captcha']) && is_int($_SESSION['captcha'])) ? $_SESSION['captcha'] : 0; - $captcha = isset($_POST['captcha']) ? controlCaptchaInput($_POST['captcha']) : 0; - + $captcha_try = isset($_POST['captcha']) ? Captcha::controlInput($_POST['captcha']) : 0; + + // II - traitement $error = ''; - if(!isset($_POST['captcha'])) // page rechargée + if(!isset($_POST['captcha'])) // page création d'un compte rechargée { //$error = ''; } - elseif($captcha == 0) + elseif($captcha_try == 0) { $error = 'error_non_valid_captcha'; } @@ -50,7 +50,7 @@ function createPassword(EntityManager $entityManager) { //$error = ''; } - elseif($captcha != $captcha_solution) // le test! + elseif($captcha_try != $captcha_solution) // le test! { $error = 'bad_solution_captcha'; } @@ -72,6 +72,8 @@ function createPassword(EntityManager $entityManager) if(isset($password) && isset($login) && $password == $_POST['password'] && $login == $_POST['login']) { + unset($_SESSION['captcha']); + // enregistrement et redirection $password = password_hash($password, PASSWORD_DEFAULT); $user = new App\Entity\User($login, $password); @@ -90,9 +92,9 @@ function createPassword(EntityManager $entityManager) } // inséré dans $captchaHtml puis dans $formulaireNouveauMDP - $captcha = createCaptcha(); + $captcha = new Captcha; // enregistrement de la réponse du captcha pour vérification - $_SESSION['captcha'] = $captcha[2]; // int + $_SESSION['captcha'] = $captcha->getSolution(); // I - affichage @@ -129,14 +131,14 @@ function connect(LoginBuilder $builder, EntityManager $entityManager) $_SESSION['admin'] = false; $captcha_solution = (isset($_SESSION['captcha']) && is_int($_SESSION['captcha'])) ? $_SESSION['captcha'] : 0; - $captcha = isset($_POST['captcha']) ? controlCaptchaInput($_POST['captcha']) : 0; + $captcha_try = isset($_POST['captcha']) ? Captcha::controlInput($_POST['captcha']) : 0; $error = ''; if(!isset($_POST['captcha'])) // page rechargée { //$error = ''; } - elseif($captcha == 0) + elseif($captcha_try == 0) { $error = 'error_non_valid_captcha'; } @@ -144,7 +146,7 @@ function connect(LoginBuilder $builder, EntityManager $entityManager) { //$error = ''; } - elseif($captcha != $captcha_solution) // le test! + elseif($captcha_try != $captcha_solution) // le test! { $error = 'bad_solution_captcha'; } @@ -162,8 +164,8 @@ function connect(LoginBuilder $builder, EntityManager $entityManager) // enregistrement et redirection if(!empty($user) && $login === $user->getLogin() && password_verify($password, $user->getPassword())) { - session_start(); session_regenerate_id(true); // protection fixation de session, si l'attaquant a créé un cookie de session (attaque XSS), il est remplacé + //unset($_SESSION['captcha']); $_SESSION['user'] = $login; $_SESSION['admin'] = true; $link = new URL(isset($_GET['from']) ? ['page' => $_GET['from']] : []); @@ -178,9 +180,9 @@ function connect(LoginBuilder $builder, EntityManager $entityManager) } // inséré dans $captchaHtml puis dans $formulaireNouveauMDP - $captcha = createCaptcha(); + $captcha = new Captcha; // enregistrement de la réponse du captcha pour vérification - $_SESSION['captcha'] = $captcha[2]; // int + $_SESSION['captcha'] = $captcha->getSolution(); // int // I - affichage $title = "Connexion"; @@ -319,36 +321,4 @@ function disconnect() isset($_GET['id']) ? $link->addParams(['id' => $_GET['id']]) : ''; header('Location: ' . $link); die; -} - - -function createCaptcha(): array -{ - $a = rand(2, 9); - $b = rand(2, 9); - return array(toLettersFrench($a), toLettersFrench($b), $a * $b); -} - -function toLettersFrench(int $number): string -{ - return match($number) - { - 2 => 'deux', - 3 => 'trois', - 4 => 'quatre', - 5 => 'cinq', - 6 => 'six', - 7 => 'sept', - 8 => 'huit', - 9 => 'neuf', - default => '', // erreur - }; -} - -// on veut des chiffres -function controlCaptchaInput(string $captcha = '0'): int -{ - // $captcha est un POST donc une chaîne, '2.3' est acceptés - // (int) supprime les décimales - return (is_numeric($captcha) && $captcha == (int) $captcha) ? (int) $captcha : 0; } \ No newline at end of file diff --git a/src/view/password.php b/src/view/password.php index aadfbae..b8a090e 100644 --- a/src/view/password.php +++ b/src/view/password.php @@ -10,14 +10,18 @@ declare(strict_types=1); // insertion du captcha -ob_start(); -?> +$captchaHtml = ''; +if(isset($captcha)) // instance de Captcha? +{ + ob_start(); + ?>

Montrez que vous n'êtes pas un robot.
- +

-

-