Partie 16 — Sessions & cookies : gérer l’état utilisateur
Le web, par défaut, est sans mémoire : tu ouvres une page, le serveur répond, puis “oublie” immédiatement. Si tu rafraîchis, tu fais une nouvelle requête, comme si tu étais un inconnu. Et pourtant, dans la vraie vie, on a besoin de mémoire : connexion, panier, langue, thème, permissions, progression…
C’est exactement le rôle des cookies et des sessions : créer un “état utilisateur” entre plusieurs pages.
👉 Dans cette partie : cookies vs sessions, comment PHP gère session_id,
login/logout, flash messages, “remember me”, expiration, et surtout
les bonnes pratiques de sécurité.
1) Cookie vs Session : la différence une fois pour toutes
On confond souvent les deux, alors clarifions simplement :
| Concept | Où c’est stocké ? | À quoi ça sert ? | Sécurité |
|---|---|---|---|
| Cookie | Navigateur (client) | Petites infos côté user (préférences, token) | Moyenne (modifiable si mal utilisé) |
| Session | Serveur | Stocker l’état (user_id, panier, rôles) | Bonne (si bien configurée) |
👉 Une session, en pratique, utilise un cookie pour transporter un identifiant :
le fameux PHPSESSID (ou un nom de cookie personnalisé).
Ce cookie contient un id, pas tes données.
Tes données restent côté serveur.
✅ Résumé : cookie = mémoire côté navigateur, session = mémoire côté serveur.
PHP relie les deux via un session_id.
2) Les cookies en PHP : setcookie(), lecture, expiration
Un cookie est une paire clé/valeur envoyée par le serveur et stockée par le navigateur. Le navigateur renvoie le cookie au serveur à chaque requête sur le même domaine (selon les règles).
2.1 Créer un cookie
Important : setcookie() doit être appelé avant tout affichage HTML (avant echo).
<?php
// Cookie valable 7 jours
setcookie("theme", "dark", time() + (7 * 24 * 60 * 60), "/");
echo "Cookie créé";
?>
2.2 Lire un cookie
<?php $theme = $_COOKIE["theme"] ?? "light"; echo "Thème actuel : " . htmlspecialchars($theme); ?>
2.3 Supprimer un cookie
Pour supprimer, on le réécrit avec une date d’expiration dans le passé.
<?php
setcookie("theme", "", time() - 3600, "/");
echo "Cookie supprimé";
?>
⚠️ Ne stocke jamais des infos sensibles (mot de passe, rôle admin, etc.) directement en cookie. Un cookie côté client peut être modifié.
3) La session en PHP : session_start(), $_SESSION, et le cycle complet
Une session se lance avec session_start(). Après, tu peux écrire et lire
dans $_SESSION comme un tableau normal.
3.1 Démarrer une session
<?php session_start(); $_SESSION["visits"] = ($_SESSION["visits"] ?? 0) + 1; echo "Nombre de visites : " . $_SESSION["visits"]; ?>
À chaque requête, PHP lit le cookie de session (ex: PHPSESSID),
retrouve les données côté serveur, et remplit $_SESSION.
3.2 Où sont stockées les sessions ?
Par défaut, PHP stocke les sessions sur le disque (ex: /tmp),
mais en production on utilise souvent :
- Redis (très courant)
- Memcached
- Base de données (moins performant mais possible)
✅ L’idée : les sessions sont côté serveur. Le client n’a que l’identifiant.
4) Login / Logout : exemple réaliste (user_id en session)
Le pattern classique : après un login réussi, tu stockes user_id dans la session.
Ensuite, sur chaque page protégée, tu vérifies si user_id existe.
4.1 Login (exemple simple)
<?php
// login.php (exemple)
session_start();
$email = $_POST["email"] ?? "";
$password = $_POST["password"] ?? "";
// Exemple (FAUX) : en vrai tu vérifies en base + password_hash/password_verify
if ($email === "user@test.com" && $password === "1234") {
$_SESSION["user_id"] = 42;
$_SESSION["user_email"] = $email;
// Très important : regénérer l'id de session après login
session_regenerate_id(true);
header("Location: dashboard.php");
exit;
}
echo "Identifiants invalides";
?>
4.2 Page protégée
<?php
// dashboard.php
session_start();
if (!isset($_SESSION["user_id"])) {
header("Location: login_form.php");
exit;
}
echo "Bienvenue ! User ID = " . (int)$_SESSION["user_id"];
?>
4.3 Logout (propre)
Un logout sérieux : vider la session et détruire le cookie de session.
<?php
session_start();
// 1) vider les variables session
$_SESSION = [];
// 2) supprimer le cookie de session si présent
if (ini_get("session.use_cookies")) {
$params = session_get_cookie_params();
setcookie(session_name(), "", time() - 42000,
$params["path"], $params["domain"],
$params["secure"], $params["httponly"]
);
}
// 3) détruire la session côté serveur
session_destroy();
header("Location: /");
exit;
?>
5) Flash messages : “succès”, “erreur” (UX pro)
Les flash messages sont des messages stockés en session pour une seule requête. Exemple : “Profil mis à jour”, “Mot de passe incorrect”.
5.1 Définir un flash
<?php
session_start();
$_SESSION["flash_success"] = "Profil mis à jour avec succès.";
header("Location: profile.php");
exit;
?>
5.2 Afficher et supprimer automatiquement
<?php
session_start();
if (!empty($_SESSION["flash_success"])) {
echo "<div style='padding:12px;background:#ecfeff;border-left:4px solid #06b6d4;'>"
. htmlspecialchars($_SESSION["flash_success"])
. "</div>";
unset($_SESSION["flash_success"]);
}
?>
✅ Cas réel : après un POST, tu rediriges (POST-Redirect-GET) et tu affiches le flash.
6) Exemple concret : panier e-commerce en session
Un panier simple : tu stockes une liste d’articles dans la session. (Dans les gros projets, tu synchronises avec la base, mais la session est parfaite pour débuter.)
<?php
session_start();
$id = (int)($_GET["id"] ?? 0);
if ($id <= 0) die("Produit invalide.");
$_SESSION["cart"] = $_SESSION["cart"] ?? [];
$_SESSION["cart"][$id] = ($_SESSION["cart"][$id] ?? 0) + 1;
echo "Produit ajouté. Panier : ";
echo "<pre>" . print_r($_SESSION["cart"], true) . "</pre>";
?>
Tu peux ensuite calculer total, quantités, etc. Et au paiement, tu vides le panier.
7) Sécurité : les réglages indispensables (HttpOnly, Secure, SameSite)
Les cookies de session doivent être configurés correctement, sinon tu risques des attaques (vol de session, fixation, CSRF).
7.1 Définir des paramètres de cookie de session
À faire avant session_start().
<?php
session_set_cookie_params([
"lifetime" => 0, // cookie session (expire à la fermeture du navigateur)
"path" => "/",
"domain" => "",
"secure" => true, // true si HTTPS
"httponly" => true, // JS ne peut pas lire le cookie
"samesite" => "Lax", // Lax / Strict / None
]);
session_start();
?>
- HttpOnly : protège contre le vol via JS (XSS)
- Secure : cookie envoyé seulement en HTTPS
- SameSite : réduit le risque CSRF (Lax est souvent un bon défaut)
⚠️ SameSite=None exige Secure=true (sinon les navigateurs bloquent souvent).
7.2 Session fixation : le bug classique
Si un attaquant arrive à faire utiliser son session_id à la victime,
puis la victime se connecte, l’attaquant récupère une session authentifiée.
Solution : regénérer l’id après login.
<?php session_start(); // après login OK : session_regenerate_id(true); ?>
7.3 Timeout : déconnecter après inactivité
Bon réflexe : si l’utilisateur est inactif 30 min, on force un logout.
<?php
session_start();
$timeout = 30 * 60; // 30 min
$now = time();
if (isset($_SESSION["last_activity"]) && ($now - $_SESSION["last_activity"]) > $timeout) {
// Inactif trop longtemps
$_SESSION = [];
session_destroy();
header("Location: login_form.php?timeout=1");
exit;
}
$_SESSION["last_activity"] = $now;
?>
Cas réel : dashboard admin, back-office, espace candidat.
8) “Remember me” : rester connecté (sans faire n’importe quoi)
Le “remember me” ne doit jamais stocker un mot de passe en cookie. La méthode propre :
- Créer un token aléatoire
- Stocker une version hashée en base (ex: sha256 ou password_hash)
- Envoyer le token brut dans un cookie sécurisé
- À la prochaine visite, comparer et recréer la session
✅ En gros : cookie = “clé”, base de données = “serrure”. Si la clé fuit, tu peux la révoquer côté serveur.
Exemple conceptuel (simplifié) :
<?php
// Génération token
$token = bin2hex(random_bytes(32)); // brut (à mettre en cookie)
$tokenHash = hash("sha256", $token); // à stocker en DB
// setcookie("remember", $token, time()+30*24*60*60, "/", "", true, true);
?>
⚠️ Pour un vrai “remember me”, il faut aussi gérer : rotation de token, device, date d’expiration, revoke.
9) Bonnes pratiques “pro” (checklist)
- Appeler
session_start()au début (avant HTML) - Configurer cookies session : HttpOnly, Secure, SameSite
- Regénérer l’id après login :
session_regenerate_id(true) - Mettre un timeout (inactivité)
- Ne jamais stocker infos sensibles en cookie
- Protéger pages privées par un “middleware” simple (fonction checkAuth)
Exemple : fonction de protection réutilisable
<?php
function requireAuth(): void
{
session_start();
if (!isset($_SESSION["user_id"])) {
header("Location: login_form.php");
exit;
}
}
// Utilisation
requireAuth();
echo "Page privée";
?>
10) Mini-exercices (pour devenir solide)
- Créer un système login/logout avec
user_iden session + redirection. - Ajouter un flash message “Connexion réussie”.
- Implémenter un timeout 15 minutes d’inactivité.
- Créer une page “admin” accessible uniquement si
$_SESSION['role'] === 'admin'. - Créer une préférence “theme” en cookie (dark/light).
Conclusion
Les sessions et cookies sont la base de tout ce qui ressemble à une application : authentification, autorisations, panier, préférences, sécurité. Si tu maîtrises : session_start(), $_SESSION, les paramètres de cookie, et la régénération d’ID, tu peux construire un système d’auth propre.
Dans la Partie 17, on pourra passer à un module très lié et très demandé : authentification complète (hash mot de passe, rôles, protections CSRF) ou sécurité web en PHP.