Semaine 3 - Jour 5 : Système d'Authentification Complet

Introduction

L'authentification est un système essentiel pour sécuriser l'accès à votre application web. Elle permet de vérifier l'identité d'un utilisateur et de protéger les données sensibles.

Dans ce cours, vous apprendrez à :
• Hacher les mots de passe de manière sécurisée avec password_hash()
• Vérifier les mots de passe avec password_verify()
• Créer un formulaire d'inscription complet
• Implémenter un système de connexion sécurisé
• Protéger des pages avec les sessions
• Gérer la déconnexion proprement

1. password_hash() : Hacher les mots de passe

Ne JAMAIS stocker les mots de passe en clair !

// ❌ DANGER : Mot de passe en clair dans la base de données INSERT INTO users (email, password) VALUES ('jean@example.com', 'monmotdepasse123'); // Si quelqu'un accède à la BDD, il voit TOUS les mots de passe !

Solution : password_hash()

PHP fournit une fonction sécurisée pour hacher (transformer) les mots de passe de manière irréversible.

<?php // Hacher un mot de passe $password = 'monmotdepasse123'; $hash = password_hash($password, PASSWORD_DEFAULT); echo "Mot de passe original : " . $password . "<br>"; echo "Hash sécurisé : " . $hash; ?>

Résultat :

Mot de passe original : monmotdepasse123
Hash sécurisé : $2y$10$X8ZQe7O7r7r2abcdefghijklmnopqrstuvwxyz123456789ABCDEFG

Important : Le hash est différent à chaque fois (grâce au "salt" automatique) !

2. password_verify() : Vérifier un mot de passe

Comparer un mot de passe avec son hash de manière sécurisée.

<?php // Le hash stocké en base de données $hash_bdd = '$2y$10$X8ZQe7O7r7r2abcdefghijklmnopqrstuvwxyz123456789ABCDEFG'; // L'utilisateur essaie de se connecter $password_saisi = 'monmotdepasse123'; // Vérifier si le mot de passe correspond if (password_verify($password_saisi, $hash_bdd)) { echo "Mot de passe correct ! Connexion réussie."; } else { echo "Mot de passe incorrect !"; } ?>
Important : password_verify() compare le mot de passe en clair avec le hash de manière sécurisée. Ne jamais comparer directement avec == !

3. Formulaire d'inscription (register.php)

Créer un compte utilisateur avec validation complète.

<?php // register.php - Inscription require_once 'db.php'; // Connexion PDO $errors = []; $success = ''; if ($_SERVER['REQUEST_METHOD'] === 'POST') { // Récupération et nettoyage des données $nom = trim($_POST['nom'] ?? ''); $prenom = trim($_POST['prenom'] ?? ''); $email = trim($_POST['email'] ?? ''); $password = $_POST['password'] ?? ''; // VALIDATION if (empty($nom)) $errors[] = "Le nom est requis."; if (empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL)) { $errors[] = "Email invalide."; } if (strlen($password) < 8) { $errors[] = "Le mot de passe doit contenir au moins 8 caractères."; } // Si pas d'erreurs, créer le compte if (empty($errors)) { // Hacher le mot de passe $password_hash = password_hash($password, PASSWORD_DEFAULT); // Insérer l'utilisateur $sql = "INSERT INTO users (nom, prenom, email, password, date_inscription) VALUES (:nom, :prenom, :email, :password, NOW())"; $stmt = $pdo->prepare($sql); $stmt->execute([ 'nom' => $nom, 'prenom' => $prenom, 'email' => $email, 'password' => $password_hash ]); $success = "Compte créé avec succès !"; } } ?>

4. Formulaire de connexion (login.php)

Système de connexion sécurisé avec sessions.

<?php // login.php - Connexion session_start(); require_once 'db.php'; $error = ''; if ($_SERVER['REQUEST_METHOD'] === 'POST') { $email = trim($_POST['email'] ?? ''); $password = $_POST['password'] ?? ''; // Rechercher l'utilisateur par email $sql = "SELECT id, nom, prenom, email, password FROM users WHERE email = :email"; $stmt = $pdo->prepare($sql); $stmt->execute(['email' => $email]); $user = $stmt->fetch(PDO::FETCH_ASSOC); // Vérifier si l'utilisateur existe et le mot de passe est correct if ($user && password_verify($password, $user['password'])) { // Régénérer l'ID de session (protection contre le session fixation) session_regenerate_id(true); // Stocker les informations en session $_SESSION['user_id'] = $user['id']; $_SESSION['user_nom'] = $user['nom']; $_SESSION['user_prenom'] = $user['prenom']; // Redirection vers le tableau de bord header('Location: dashboard.php'); exit(); } else { $error = "Email ou mot de passe incorrect."; } } ?>

5. Protection de pages (dashboard.php)

Vérifier qu'un utilisateur est connecté avant d'afficher le contenu.

<?php // dashboard.php - Page protégée session_start(); // Vérifier si l'utilisateur est connecté if (!isset($_SESSION['user_id'])) { // Si non connecté, rediriger vers la page de connexion header('Location: login.php'); exit(); } // L'utilisateur est connecté, afficher le contenu $prenom = htmlspecialchars($_SESSION['user_prenom']); echo "Bienvenue, $prenom !"; ?>

Fichier de protection réutilisable (check_auth.php)

<?php // check_auth.php - À inclure sur chaque page protégée session_start(); if (!isset($_SESSION['user_id'])) { header('Location: login.php'); exit(); } ?>

6. Déconnexion (logout.php)

Détruire la session complètement et rediriger.

<?php // logout.php - Déconnexion complète session_start(); // Détruire toutes les variables de session $_SESSION = []; // Détruire le cookie de session si il existe if (isset($_COOKIE[session_name()])) { setcookie(session_name(), '', time() - 3600, '/'); } // Détruire la session session_destroy(); // Rediriger vers la page de connexion header('Location: login.php'); exit(); ?>
Ordre des opérations de déconnexion :
  1. session_start() : Démarrer la session
  2. $_SESSION = [] : Vider les variables
  3. setcookie() : Supprimer le cookie (optionnel mais recommandé)
  4. session_destroy() : Détruire la session
  5. header('Location: ...') : Rediriger

7. session_regenerate_id() : Protection contre le session fixation

Régénérer l'ID de session après une connexion réussie.

Qu'est-ce que le session fixation ?

Une attaque où un hacker force l'utilisateur à utiliser un ID de session connu. En régénérant l'ID après la connexion, on empêche cette attaque.

<?php // Après une connexion réussie session_regenerate_id(true); // true = détruire l'ancien ID // Maintenant stocker les données de l'utilisateur $_SESSION['user_id'] = $user_id; ?>

8. Structure SQL pour le système d'authentification

Table users pour stocker les comptes utilisateurs.

-- Création de la table users CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, nom VARCHAR(100) NOT NULL, prenom VARCHAR(100) NOT NULL, email VARCHAR(255) NOT NULL UNIQUE, password VARCHAR(255) NOT NULL, date_inscription DATETIME DEFAULT CURRENT_TIMESTAMP, derniere_connexion DATETIME, actif TINYINT(1) DEFAULT 1 ); -- Index pour optimiser les recherches par email CREATE INDEX idx_email ON users(email);

Récapitulatif du flux d'authentification

1. Inscription

  1. Valider les données
  2. Vérifier si email existe
  3. password_hash()
  4. INSERT en base
  5. Redirection vers login

2. Connexion

  1. SELECT par email
  2. password_verify()
  3. session_regenerate_id()
  4. Stocker en $_SESSION
  5. Redirection dashboard

3. Pages protégées

  1. session_start()
  2. Vérifier $_SESSION['user_id']
  3. Si absent : redirection login
  4. Si présent : afficher page

4. Déconnexion

  1. session_start()
  2. $_SESSION = []
  3. Supprimer cookie
  4. session_destroy()
  5. Redirection login

Checklist de sécurité pour l'authentification

Froggiesplaining :


Objectifs de ce cours :
✅ Comprendre pourquoi ne JAMAIS stocker les mots de passe en clair
✅ Utiliser password_hash() pour sécuriser les mots de passe
✅ Implémenter un système d'inscription complet avec validation
✅ Créer un système de connexion sécurisé avec sessions
✅ Protéger des pages avec vérification de session
✅ Gérer la déconnexion proprement
✅ Se protéger contre le session fixation

Points clés à retenir :
password_hash() transforme le mot de passe en code secret illisible (hash)
• Même si un héron vole le hash, il ne peut pas retrouver le mot de passe original !
• Chaque hash est unique grâce au "salt" automatique
password_verify() compare le mot de passe saisi avec le hash de manière sécurisée
• Les sessions stockent les informations de l'utilisateur connecté
session_regenerate_id() empêche les attaques de session fixation
• Toujours vérifier $_SESSION['user_id'] sur les pages protégées
• Messages d'erreur vagues : "Email ou mot de passe incorrect" (pas "Cet email n'existe pas")
• Min 8 caractères pour le mot de passe, mais 12+ c'est mieux !

Exercice pratique :
1. Créez une table users dans votre base de données
2. Créez un fichier register.php avec formulaire d'inscription
3. Implémentez la validation et le hachage du mot de passe
4. Créez un fichier login.php avec système de connexion
5. Créez une page protégée dashboard.php qui vérifie la session
6. Testez le système complet : inscription → connexion → accès au dashboard → déconnexion
7. Essayez d'accéder au dashboard sans être connecté (vous devez être redirigé vers login)

Froggie explain

GitHub - eCrea