2.2Sessions & cookies (authentification simple)
Le protocole HTTP est sans état (stateless) : chaque requête est INDÉPENDANTE, le serveur ne « se souvient » pas des requêtes précédentes. Or une application a souvent besoin de MÉMORISER un état d'une page à l'autre : qui est connecté, le contenu d'un panier, des préférences. Deux mécanismes permettent cette « mémoire » : les cookies et les sessions. Les cookies : de petites données stockées dans le NAVIGATEUR de l'utilisateur, renvoyées au serveur à chaque requête. On les crée avec setcookie() et on les lit dans la superglobale $_COOKIE. Un cookie a une durée de vie, un domaine, un chemin, et des options de sécurité importantes (HttpOnly — inaccessible au JavaScript, contre le vol par XSS ; Secure — envoyé seulement en HTTPS ; SameSite — contre le CSRF). Les cookies sont stockés CÔTÉ CLIENT — donc modifiables par l'utilisateur et à ne pas utiliser pour des données sensibles ou de confiance directement.
Les sessions : le mécanisme privilégié pour conserver un état SÉCURISÉ côté serveur. Le principe : les données de session sont stockées CÔTÉ SERVEUR (l'utilisateur ne peut pas les modifier), et le navigateur ne conserve qu'un identifiant de session (un cookie contenant un identifiant unique) qui permet au serveur de retrouver les bonnes données à chaque requête. En PHP : session_start() (au tout début du script, avant toute sortie) démarre/reprend la session, puis on stocke et lit des données via la superglobale $_SESSION ($_SESSION['user_id'] = 42;). Les sessions servent notamment à l'authentification : quand un utilisateur se connecte (on vérifie son identifiant et son mot de passe), on stocke son identité en session ($_SESSION['user_id']) ; sur chaque page protégée, on vérifie que la session contient un utilisateur connecté (sinon on redirige vers la connexion) ; à la déconnexion, on détruit la session (session_destroy()). Points de sécurité ESSENTIELS pour une authentification, même « simple ». (1) Les mots de passe se stockent HACHÉS (jamais en clair) avec password_hash(), et se vérifient avec password_verify() (détaillé en 3-4) — c'est non négociable. (2) La session doit être protégée : régénérer l'identifiant de session à la connexion (session_regenerate_id(), contre la « fixation de session »), utiliser des cookies de session sécurisés (HttpOnly, Secure, SameSite), et HTTPS. (3) Contrôler 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). Comprendre les sessions et cookies — et bâtir une authentification correcte (sessions côté serveur, mots de passe hachés, session protégée) — est fondamental : c'est ce qui permet des applications avec des comptes utilisateurs, des espaces personnels, des paniers. Et c'est un domaine à fort enjeu de sécurité, où les erreurs (mots de passe mal stockés, sessions mal protégées) ont des conséquences graves.
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.
- Cookies ($_COOKIE)
- Petites données stockées dans le NAVIGATEUR, renvoyées à chaque requête (setcookie / $_COOKIE) ; côté client (modifiables) — options de sécurité HttpOnly, Secure, SameSite.
- Sessions ($_SESSION)
- État stocké CÔTÉ SERVEUR (non modifiable par l'utilisateur), le navigateur ne gardant qu'un identifiant de session. session_start() puis $_SESSION. Le mécanisme sécurisé.
- Authentification par session
- Connexion : vérifier identifiant + mot de passe, stocker l'identité en session ; pages protégées : vérifier la session ; déconnexion : détruire la session.
- Sécurité de session
- Mots de passe HACHÉS (password_hash/verify), régénérer l'ID à la connexion (contre la fixation), cookies sécurisés (HttpOnly/Secure/SameSite), HTTPS, et contrôle des accès (autorisation).
Cookies ou sessions pour l'état sensible (qui est connecté) ?
En pratique — Gérer l'état et une authentification simple
- Démarrez une session (`session_start()` au début du script) et stockez/lisez des données via $_SESSION.
- Créez un cookie avec setcookie() (avec options HttpOnly/Secure) et lisez-le via $_COOKIE ; comprenez qu'il est stocké côté client (modifiable).
- 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.
- 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.
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. `session_start()` puis $_SESSION. 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).
Questions fréquentes
Cookies ou sessions : quelle différence, et lequel utiliser pour quoi ?
Cookies et sessions résolvent le même problème (donner une « mémoire » à HTTP, qui est sans état) mais de façon différente, avec des implications de SÉCURITÉ importantes — voici comment les distinguer et choisir. Le problème commun : HTTP est SANS ÉTAT — chaque requête est indépendante, le serveur ne se souvient pas des précédentes. Pour mémoriser un état entre les pages (qui est connecté, un panier, des préférences), il faut un mécanisme. Cookies et sessions en sont deux. Les COOKIES : (1) Où sont stockées les données : dans le NAVIGATEUR de l'utilisateur (côté client). Le navigateur renvoie le cookie au serveur à chaque requête. (2) Contrôle : les données sont chez l'utilisateur, donc VISIBLES et MODIFIABLES par lui (il peut voir et changer un cookie). (3) Capacité : petite (limitée en taille). (4) Persistance : un cookie peut persister longtemps (avec une date d'expiration) — utile pour se souvenir de quelque chose entre les visites (« se souvenir de moi », préférences). (5) Sécurité : comme les données sont côté client (modifiables), les cookies ne doivent PAS contenir de données sensibles ou de confiance en clair. Les options HttpOnly (inaccessible au JavaScript, contre le vol par XSS), Secure (HTTPS seulement), SameSite (contre le CSRF) sont importantes pour les sécuriser. Les SESSIONS : (1) Où sont stockées les données : côté SERVEUR (chez vous). Le navigateur ne garde qu'un IDENTIFIANT de session (un cookie contenant un identifiant unique) qui permet au serveur de retrouver les données. (2) Contrôle : les données sont côté serveur, donc l'utilisateur NE PEUT PAS les modifier (il n'a que l'identifiant). C'est plus SÛR pour les données de confiance. (3) Capacité : plus grande (côté serveur). (4) Persistance : la session dure généralement le temps de la visite (elle expire après un temps d'inactivité ou à la fermeture du navigateur). (5) Sécurité : bien plus adaptée aux données sensibles (identité de l'utilisateur connecté), puisque l'utilisateur ne voit/modifie que l'identifiant, pas les données. Le lien entre les deux : les sessions UTILISENT généralement un cookie (pour stocker l'identifiant de session côté navigateur) — donc les sessions reposent sur un cookie, mais les DONNÉES restent côté serveur. C'est la différence clé : cookie = données côté client ; session = données côté serveur (avec juste l'identifiant côté client). Lequel utiliser pour quoi : (1) SESSIONS pour l'état SENSIBLE / de confiance : l'AUTHENTIFICATION (qui est connecté — $_SESSION['user_id']), les données de confiance liées à l'utilisateur connecté, le panier d'achat, tout ce qui ne doit PAS être modifiable par l'utilisateur. Les sessions sont le choix par défaut pour l'état applicatif sécurisé. (2) COOKIES pour les préférences NON sensibles et la persistance longue : se souvenir d'un choix de langue, d'un thème, du « se souvenir de moi » (avec précautions — un jeton sûr, pas les identifiants), des préférences d'affichage. Des données que l'utilisateur pourrait voir/modifier sans conséquence grave, et qu'on veut conserver entre les visites (au-delà d'une session). (3) Cas courant du « se souvenir de moi » : un cookie persistant contenant un JETON SÛR (pas le mot de passe !) qui permet de reconnecter l'utilisateur automatiquement — à implémenter avec soin (jeton aléatoire, stocké et vérifié côté serveur, révocable). Les points de sécurité (pour les deux) : (1) Cookies : options HttpOnly, Secure, SameSite ; ne pas y mettre de données sensibles ou de confiance. (2) Sessions : régénérer l'identifiant à la connexion (contre la fixation de session), cookie de session sécurisé (HttpOnly, Secure, SameSite), expiration appropriée, HTTPS. (3) HTTPS est important dans les deux cas (chiffre le transport, protège les cookies/identifiants de l'interception). En résumé : les cookies stockent des données CÔTÉ CLIENT (visibles, modifiables par l'utilisateur, petite taille, persistance possible) — pour les préférences non sensibles et la persistance longue ; les sessions stockent des données CÔTÉ SERVEUR (non modifiables par l'utilisateur, l'utilisateur ne garde qu'un identifiant) — pour l'état sensible/de confiance (authentification, panier). La règle : SESSIONS pour tout ce qui touche à la sécurité et à la confiance (qui est connecté, données sensibles), COOKIES pour les préférences non critiques et la persistance entre visites. Sécurisez les deux (options de cookie, régénération d'identifiant, HTTPS). Cette distinction est fondamentale pour bâtir des applications avec comptes et état, en toute sécurité — utiliser un cookie pour des données de confiance (modifiables par l'utilisateur) serait une faille.
Comment construire une authentification correcte, et quels sont les pièges de sécurité à éviter ?
L'authentification (vérifier l'identité des utilisateurs) est un domaine à fort enjeu où les erreurs ont des conséquences graves (comptes compromis, fuites) — voici comment la construire correctement et les pièges à éviter absolument. Les étapes d'une authentification par session : (1) INSCRIPTION : l'utilisateur fournit ses informations (email, mot de passe) ; vous VALIDEZ (email valide, mot de passe assez fort), vous HACHEZ le mot de passe avec password_hash(), et vous stockez l'utilisateur en base (avec le HASH, jamais le mot de passe en clair). (2) CONNEXION : l'utilisateur fournit email + mot de passe ; vous récupérez l'utilisateur en base par son email, vous VÉRIFIEZ le mot de passe avec password_verify() (qui compare le mot de passe fourni au hash stocké) ; si correct, vous démarrez/regénérez la session et stockez l'identité ($_SESSION['user_id'] = ...). (3) PAGES PROTÉGÉES : sur chaque page nécessitant une connexion, vous VÉRIFIEZ que la session contient un utilisateur connecté (isset($_SESSION['user_id'])) ; sinon, vous redirigez vers la page de connexion. (4) AUTORISATION : au-delà de « est-il connecté ? » (authentification), vérifiez « a-t-il le DROIT d'accéder à CETTE ressource ? » (autorisation) — un utilisateur connecté ne doit pas accéder aux données d'un AUTRE utilisateur. (5) DÉCONNEXION : détruisez la session (session_destroy(), videz $_SESSION). Les PIÈGES de sécurité à éviter absolument : (1) Stocker les mots de passe en CLAIR (ou mal hachés). LE piège n°1 et le plus grave. Ne JAMAIS stocker un mot de passe en clair (une fuite de base exposerait tous les mots de passe). Utilisez password_hash() (qui utilise un algorithme sûr, bcrypt/Argon2, avec sel et coût — comme vu pour Node avec bcrypt) et password_verify(). N'utilisez PAS de hachage simple (md5, sha1 — trop rapides, cassables) ni de hachage « maison ». password_hash fait tout correctement — utilisez-le. (Détaillé en 3-4.) (2) Ne pas régénérer l'identifiant de session à la connexion. Sans session_regenerate_id() à la connexion, votre application est vulnérable à la « FIXATION DE SESSION » (un attaquant impose un identifiant de session connu à la victime, puis l'utilise une fois qu'elle s'est connectée). Régénérez l'identifiant après une connexion réussie. (3) Cookies de session non sécurisés. Le cookie de session doit être HttpOnly (inaccessible au JavaScript — contre le vol par XSS), Secure (HTTPS seulement) et SameSite (contre le CSRF). (4) Pas de HTTPS. Sans HTTPS, les identifiants (mot de passe à la connexion, identifiant de session) circulent en clair et peuvent être interceptés. HTTPS est indispensable pour toute authentification. (5) Oublier l'AUTORISATION. Vérifier qu'un utilisateur est connecté (authentification) NE SUFFIT PAS — il faut vérifier qu'il a le DROIT d'accéder à CE contenu (autorisation). Un piège classique et grave : un utilisateur connecté peut accéder aux données d'un autre en changeant un identifiant dans l'URL (profil.php?id=42 → il met un autre id) si vous ne vérifiez pas qu'il a le droit. TOUJOURS contrôler les droits d'accès. (6) Messages d'erreur trop précis à la connexion. Ne dites pas « email inconnu » vs « mot de passe incorrect » (cela révèle quels emails existent) — un message générique (« identifiants incorrects ») est plus sûr. (7) Ne pas limiter les tentatives. Sans limitation (rate limiting), un attaquant peut tenter des milliers de mots de passe (force brute). Limitez les tentatives de connexion. (8) Injection SQL à la connexion : utilisez des REQUÊTES PRÉPARÉES pour récupérer l'utilisateur (jamais de concaténation — sinon injection SQL, section 3-1/3-4). (9) Failles XSS/CSRF : protégez vos formulaires (jetons CSRF, échappement — section 3-4). Les bonnes pratiques résumées : (1) mots de passe HACHÉS avec password_hash/password_verify (jamais en clair) ; (2) régénérer l'identifiant de session à la connexion ; (3) cookies de session sécurisés (HttpOnly, Secure, SameSite) ; (4) HTTPS obligatoire ; (5) AUTORISATION (vérifier les droits, pas juste la connexion) ; (6) requêtes préparées ; (7) messages d'erreur génériques ; (8) limiter les tentatives ; (9) protéger contre XSS/CSRF. Une note importante : construire soi-même une authentification est FORMATEUR (comprendre les mécanismes), mais en PROJET RÉEL, il est souvent recommandé d'utiliser les systèmes d'authentification ÉPROUVÉS des frameworks (Laravel, Symfony ont des systèmes d'auth robustes et testés, section 4-2/4-4 pour les API) — ils gèrent correctement toutes ces subtilités de sécurité, évitant les erreurs. Réinventer l'authentification à la main en production est risqué (facile d'oublier une protection) ; s'appuyer sur des solutions éprouvées est plus sûr. En résumé : une authentification correcte suit les étapes (inscription avec hachage, connexion avec vérification, pages protégées, autorisation, déconnexion) et évite les pièges graves (mots de passe en clair — le pire, fixation de session, cookies non sécurisés, pas de HTTPS, oubli de l'autorisation, injection SQL). La sécurité de l'authentification est à fort enjeu (comptes de vraies personnes) — appliquez rigoureusement les bonnes pratiques (hachage, session protégée, HTTPS, autorisation), et en production, privilégiez les systèmes d'auth éprouvés des frameworks. Comprendre ces mécanismes (comme le fait cette section) est essentiel ; les implémenter avec toute la rigueur de sécurité l'est encore plus. C'est une responsabilité : vous protégez les comptes et données de vos utilisateurs.