2.2 · Sessions, cookies & authentification simple

Niveau 2 · PHP & le Web

2.2Sessions, cookies & authentification simple

Objectif : Conserver un état entre les pages (sessions côté serveur, cookies) et bâtir une authentification simple mais SÛRE (mots de passe hachés, session protégée) — la base des comptes utilisateurs.
Temps estimé : 11 min · lecture autonome · Si vous n'avez que 5 min : lisez « L'essentiel en 30s » + le schéma.

L'essentiel en 30 secondes

  • HTTP oublie tout : chaque requête est indépendante — cookies et sessions ajoutent la « mémoire » entre les pages (qui est connecté, panier, préférences).
  • Sessions pour le sensible, cookies pour les préférences : données de confiance côté SERVEUR ($_SESSION, non modifiables) — jamais de donnée sensible dans un cookie modifiable.
  • Mots de passe hachés, jamais en clair : password_hash à l'inscription, password_verify à la connexion, ID de session régénéré — aucune exception.

Mini-cas filé — Riad garde ses adhérents connectés

Riad enchaîne sur son formulaire (2.1) : les adhérents de l'association doivent rester connectés d'une page à l'autre pour voir leur espace personnel. HTTP étant sans état, il ajoute une mémoire : un cookie pour la préférence de langue (non sensible), une session pour l'identité (sensible, côté serveur). À la connexion il vérifie le mot de passe avec password_verify sur un hash, régénère l'ID de session, stocke l'identifiant en $_SESSION ; chaque page protégée vérifie la session. En 2.3, il factorisera la vérification dans un fichier inclus partout ; en 2.4, il datera la dernière connexion.

Suite du fil rouge 2.1 : le formulaire de Riad devient un espace adhérents avec mémoire — et continue en 2.3 et 2.4.

1. Donner une mémoire à HTTP : cookies et sessions

Le protocole HTTP est sans état (stateless) : chaque requête est INDÉPENDANTE, le serveur ne « se souvient » de rien entre deux pages. Pour mémoriser un état (qui est connecté, un panier, des préférences), deux mécanismes. Les cookies : de petites données stockées dans le NAVIGATEUR, renvoyées au serveur à chaque requête — créées avec setcookie(), lues dans $_COOKIE. Côté client, donc VISIBLES et MODIFIABLES par l'utilisateur : réservés aux données non sensibles (langue, thème), avec des options de sécurité (HttpOnly contre le vol par XSS, Secure pour HTTPS seul, SameSite contre le CSRF). Les sessions : l'état est stocké côté SERVEUR (l'utilisateur ne peut pas le modifier), le navigateur ne conservant qu'un identifiant de session. En PHP : session_start() tout au début du script (avant toute sortie), puis stockage et lecture via $_SESSION ($_SESSION['user_id'] = 42;). Les données sensibles vivent en session — jamais en clair dans un cookie. Riad l'applique : langue en cookie, identité en session.

2. Une authentification simple mais sûre

Les sessions servent notamment à l'authentification. Le cycle : à la CONNEXION, on vérifie l'identifiant et le mot de passe, puis on stocke l'identité en session ($_SESSION['user_id']) ; sur chaque page PROTÉGÉE, on vérifie la session (sinon redirection vers la connexion) ; à la DÉCONNEXION, on détruit la session (session_destroy()). Trois protections sont non négociables. D'abord, les mots de passe se stockent HACHÉS avec password_hash() et se vérifient avec password_verify() — jamais en clair, jamais avec un hachage faible : une fuite de base exposerait sinon tous les comptes. Ensuite, on régénère l'identifiant à la connexion (session_regenerate_id()) contre la fixation de session, avec des cookies de session sécurisés et HTTPS. Enfin, on contrôle les ACCÈS : vérifier non seulement que l'utilisateur est connecté (authentification), mais qu'il a le DROIT d'accéder à la ressource (autorisation) — sinon un adhérent lit les données d'un autre en changeant un id dans l'URL.

3. Les pièges qui compromettent des comptes

L'authentification est un domaine à fort enjeu : une erreur compromet de vrais comptes. Les pièges à bannir : stocker un mot de passe en clair ; oublier de régénérer l'ID de session ; laisser les cookies de session sans HttpOnly/Secure/SameSite ; travailler sans HTTPS ; vérifier la connexion mais pas l'autorisation ; révéler par des messages d'erreur trop précis quels e-mails existent ; ne pas limiter les tentatives (force brute) ; construire les requêtes par concaténation au lieu de requêtes préparées (injection SQL, niveau 3). Riad a coché chaque point avant d'ouvrir l'espace adhérents. Et en PROJET RÉEL, on privilégie les systèmes d'authentification ÉPROUVÉS des frameworks, qui gèrent correctement ces subtilités : comprendre les mécanismes (comme ici) est essentiel, les implémenter avec rigueur l'est encore plus.

Erreur d'interprétation fréquente : « Stocker l'identifiant dans un cookie, c'est pareil qu'une session — et plus simple ». Non. Un cookie vit dans le navigateur : l'utilisateur le voit, le modifie, le falsifie — y mettre « user_id = 1 » ou un rôle, c'est laisser chacun s'attribuer l'identité qu'il veut. La session garde les données côté serveur, hors d'atteinte : le navigateur ne détient qu'un identifiant opaque. La règle de Riad est sans appel : tout ce qui fait confiance (identité, rôle, panier) vit en $_SESSION ; le cookie ne porte que des préférences non critiques, sécurisé par HttpOnly, Secure et SameSite.
Cookies vs sessions Client vs serveur CookiesDonnées côté client (modifiables) — préférences+SessionsDonnées côté serveur (sûres) — identité, panier+SécuritéHachage, ID régénéré, HTTPS, autorisation Sessions pour l'état sensible ; cookies pour les préférences non critiques.
Client vs serveur
Version texte du schéma (SEO / lecteurs d'écran / traduction) : 1) HTTP est SANS ÉTAT : Riad doit ajouter une mémoire pour garder ses adhérents connectés. 2) Les COOKIES stockent des préférences côté client (langue) — modifiables, donc jamais de donnée sensible, avec HttpOnly, Secure, SameSite. 3) Les SESSIONS stockent l'identité côté serveur via session_start puis $_SESSION — le navigateur ne garde qu'un identifiant. 4) La SÉCURITÉ verrouille le tout : mots de passe hachés (password_hash/verify), ID régénéré à la connexion, HTTPS, et autorisation vérifiée sur chaque page. Leçon : sensible = serveur, préférences = cookie.

🔎 Exemple concret — 🔎 Exemple concret — La connexion des adhérents de Riad

Session + mot de passe haché, comme chez Riad :

session_start();
if (password_verify($_POST['mdp'] ?? '', $user['hash'])) {
  session_regenerate_id(true);
  $_SESSION['user_id'] = (int) $user['id'];
}
// page protégée :
// if (!isset($_SESSION['user_id'])) { header('Location: connexion.php'); exit; }

Lecture : vérification sur le hash, ID régénéré contre la fixation, identité côté serveur.

Leçon : vérifier aussi l'autorisation (le DROIT d'accès), pas juste la connexion.

Vocabulaire de la section

HTTP sans état (stateless)
Chaque requête HTTP est indépendante, le serveur ne se souvient pas des précédentes ; cookies et sessions ajoutent une mémoire entre les pages.

Exemple simple : Riad doit ajouter une mémoire pour garder ses adhérents connectés.

Ce que ce n'est pas : un serveur qui reconnaît spontanément ses visiteurs.

Réflexe : état entre pages = cookie ou session à prévoir.

Cookies ($_COOKIE)
Petites données stockées dans le NAVIGATEUR, renvoyées à chaque requête (setcookie / $_COOKIE) ; côté client donc modifiables — options HttpOnly, Secure, SameSite.

Exemple simple : Riad mémorise la langue choisie dans un cookie.

Ce que ce n'est pas : un stockage sûr pour l'identité ou un rôle.

Réflexe : cookie = préférences non sensibles uniquement.

Sessions ($_SESSION)
État stocké CÔTÉ SERVEUR, non modifiable par l'utilisateur, le navigateur ne gardant qu'un identifiant ; session_start() puis $_SESSION — le mécanisme sécurisé.

Exemple simple : L'identité des adhérents de Riad vit en $_SESSION['user_id'].

Ce que ce n'est pas : une donnée que l'utilisateur peut éditer dans son navigateur.

Réflexe : donnée de confiance = session.

Authentification par session
Connexion : vérifier identifiant + mot de passe puis stocker l'identité en session ; pages protégées : vérifier la session ; déconnexion : détruire la session.

Exemple simple : Riad protège l'espace adhérents par isset($_SESSION['user_id']).

Ce que ce n'est pas : une page qui fait confiance à un cookie modifiable.

Réflexe : chaque page sensible = vérification de session.

Sécurité de session
Mots de passe HACHÉS (password_hash/verify, jamais en clair), ID régénéré à la connexion, cookies sécurisés, HTTPS, et contrôle des accès.

Exemple simple : Riad hache à l'inscription et vérifie avec password_verify.

Ce que ce n'est pas : un mot de passe stocké en clair ou en md5.

Réflexe : nouvelle authentification = checklist sécurité complète.

En pratique — En pratique — Gérer l'état et une authentification simple

  1. Démarrez une session (session_start() au début du script, avant toute sortie) et stockez/lisez des données via $_SESSION.
  2. Créez un cookie avec setcookie() (options HttpOnly/Secure) et lisez-le via $_COOKIE ; comprenez qu'il est stocké côté client (modifiable).
  3. Bâtissez une authentification : à la connexion, vérifiez le mot de passe (password_verify sur un hash), stockez $_SESSION['user_id'], régénérez l'ID de session.
  4. Protégez les pages (vérifier la session, rediriger sinon) et gérez la déconnexion (session_destroy) ; retenez : mots de passe HACHÉS, session protégée, HTTPS.
Vous conservez un état entre les pages (sessions côté serveur, cookies) et bâtissez une authentification simple mais SÛRE (mots de passe hachés, session protégée) — la base des comptes utilisateurs.

Script prêt à dire — justifier la session au responsable associatif (30 s)

« Pour l'espace adhérents, l'identité vit en session, côté serveur : l'adhérent ne peut pas la modifier. Le cookie ne porte que la langue. Les mots de passe sont hachés, jamais en clair, et je régénère l'identifiant à chaque connexion. Si quelqu'un falsifie son cookie, il ne gagne aucun accès. »

À dire en montrant un cookie modifié qui ne donne aucun accès ; la démonstration convainc.

Modèle copier-coller — connexion et page protégée

' . htmlspecialchars('Identifiants invalides.', ENT_QUOTES, 'UTF-8') . '

'; // --- page protégée (espace.php) --- // session_start(); // if (!isset($_SESSION['user_id'])) { header('Location: connexion.php'); exit; } // --- déconnexion --- // $_SESSION = []; session_destroy();

Préférence de langue

Riad mémorise le français ou l'arabe dans un cookie longue durée : non sensible, parfait pour le client.

Panier sensible

Le contenu du panier de la boutique associative vit en session : l'adhérent ne peut pas modifier les prix.

Déconnexion propre

Un clic vide $_SESSION et détruit la session : sur un ordinateur partagé, aucun successeur ne récupère le compte.

Vers le framework

En projet réel, Riad confiera l'authentification au système éprouvé du framework — mêmes principes, subtilités gérées.

Prudence : Ne stockez JAMAIS un mot de passe en clair (ni avec un hachage faible) : une fuite de base exposerait tous les comptes, avec des conséquences graves pour de vraies personnes. Utilisez password_hash à l'inscription et password_verify à la connexion, sans exception. Ce guide pose les gestes de base — faites relire toute authentification réelle par un développeur expérimenté avant la mise en ligne.

✓ Bonnes pratiques

  • Utiliser les SESSIONS pour l'état sensible (identité, panier).
  • Hacher les mots de passe avec password_hash / password_verify, jamais en clair.
  • Régénérer l'ID de session à la connexion + cookies sécurisés + HTTPS.

✗ Pièges fréquents

  • Stocker des données de confiance dans un cookie (modifiable par l'utilisateur).
  • Stocker un mot de passe en clair ou avec md5/sha1.
  • Vérifier seulement la connexion et oublier l'autorisation (accès aux données d'autrui).

Points clés à retenir

  • HTTP est SANS ÉTAT (chaque requête indépendante) ; COOKIES (côté navigateur, $_COOKIE) et SESSIONS (côté serveur, $_SESSION) ajoutent une « mémoire » entre les pages.
  • SESSIONS = mécanisme SÉCURISÉ : données côté serveur (non modifiables), le navigateur ne garde qu'un IDENTIFIANT. Cookies = côté client (modifiables, pour données non sensibles).
  • AUTHENTIFICATION : connexion (vérifier mot de passe, stocker l'identité en session) → pages protégées (vérifier la session) → déconnexion (détruire).
  • SÉCURITÉ (à fort enjeu) : mots de passe HACHÉS (password_hash/verify, JAMAIS en clair), régénérer l'ID à la connexion, cookies sécurisés (HttpOnly/Secure/SameSite), HTTPS, contrôle des accès (autorisation).

Défi 48h — appliquez demain

Bâtissez une connexion minimale : un hash créé avec password_hash, vérification avec password_verify, session_regenerate_id, stockage de l'identité en session, une page protégée qui redirige sinon, et une déconnexion. Puis falsifiez votre cookie et constatez que l'accès reste refusé.

Checklist sortie de section
  • Je peux expliquer la différence cookie/session et dire où vit chaque donnée.
  • Je sais bâtir une connexion avec hash, session régénérée et page protégée.
  • J'ai vérifié qu'un cookie falsifié ne donne aucun accès.
Auto-évaluation 1-5 : est-ce que je mets chaque donnée du bon côté (serveur vs client) ?est-ce que je refuse tout mot de passe en clair ?

Questions fréquentes

Cookies ou sessions : quelle différence, et lequel utiliser pour quoi ?

Les deux donnent une « mémoire » à HTTP, mais différemment. COOKIES : données dans le NAVIGATEUR (côté client), renvoyées à chaque requête — VISIBLES et MODIFIABLES par l'utilisateur, petite taille, persistance longue possible ; jamais de données sensibles en clair (options HttpOnly, Secure, SameSite). SESSIONS : données côté SERVEUR, le navigateur ne gardant qu'un IDENTIFIANT ; l'utilisateur NE PEUT PAS modifier les données ; capacité plus grande ; dure généralement la visite. Les sessions utilisent un cookie (pour l'identifiant) mais les DONNÉES restent serveur — c'est la différence clé. Utilisez les SESSIONS pour l'état SENSIBLE (authentification, panier) — le choix par défaut ; les COOKIES pour les préférences NON sensibles et la persistance longue (langue, thème). Sécurisez les deux (options de cookie, régénération d'identifiant, HTTPS).

Comment construire une authentification correcte, et quels pièges éviter ?

Étapes : (1) INSCRIPTION — valider, HACHER avec password_hash(), stocker le HASH (jamais le clair). (2) CONNEXION — récupérer l'utilisateur par e-mail (requête PRÉPARÉE), vérifier avec password_verify(), puis session_regenerate_id() et stocker l'identité en session. (3) PAGES PROTÉGÉES — vérifier la session (isset($_SESSION['user_id'])), sinon rediriger. (4) AUTORISATION — vérifier le DROIT sur CETTE ressource, pas juste la connexion. (5) DÉCONNEXION — vider puis détruire la session. Pièges graves : mots de passe en CLAIR ou mal hachés (le pire), ID non régénéré (fixation), cookies non sécurisés, pas de HTTPS, autorisation oubliée, messages d'erreur révélant les e-mails, tentatives illimitées (force brute), requêtes concaténées (injection SQL). En PROJET RÉEL, privilégiez les systèmes d'authentification ÉPROUVÉS des frameworks.

Vérifiez votre compréhension

Où sont stockées les données d'une SESSION ?

Ressources supplémentaires (optionnel, pour aller plus loin)

Examen du niveau 2Questions inédites et durcies pour valider vos acquis