Une PHP session est le moyen le plus fondamental de se souvenir d'un utilisateur d'une page à l'autre, alors que le protocole HTTP est sans état. Lorsqu'une personne se connecte, ajoute un article au panier ou change sa préférence de langue, vous devez le savoir lors de la requête suivante également. Les sessions et les cookies fonctionnent ensemble pour rendre cela possible. Dans cet article, vous verrez pas à pas comment les deux fonctionnent, quels réglages les sécurisent et comment se défendre contre des attaques typiques comme la fixation de session.
La différence entre une session et un cookie
Les deux sont souvent confondus, mais leurs rôles diffèrent. Un cookie est une petite donnée stockée dans le navigateur et renvoyée au serveur à chaque requête. Une session est un mécanisme où la donnée réside côté serveur ; le navigateur ne conserve qu'un identifiant (le session ID) qui pointe vers elle. Cette distinction est importante : les données sensibles comme l'e-mail de l'utilisateur ou son niveau de droits restent sur le serveur, et seul un identifiant impossible à deviner voyage vers le navigateur.
- Cookie : dans le navigateur, en clair. L'utilisateur peut le lire et le modifier. Adapté aux données non sensibles comme la préférence de langue ou le thème.
- Session : sur le serveur. L'utilisateur ne possède que l'identifiant et ne voit pas son contenu. Le bon choix pour l'authentification et l'état sensible.
Démarrer une session
Une session commence toujours par session_start(). Cet appel doit avoir lieu avant tout envoi de sortie — c'est-à-dire avant tout echo ou HTML — sinon vous obtenez l'erreur « headers already sent ». Une fois démarrée, vous lisez et écrivez les données via le tableau superglobal $_SESSION.
<?php
session_start();
// Écrire des données
$_SESSION['user_id'] = 42;
$_SESSION['locale'] = 'fr';
// Lire des données
$userId = $_SESSION['user_id'] ?? null;
Par défaut, les données de session sont stockées dans un fichier sur le serveur, et le session ID est envoyé au navigateur dans un cookie nommé PHPSESSID. Un cookie est donc déjà utilisé en coulisses ; c'est pourquoi les réglages du cookie qui protège le session ID affectent directement sa sécurité.
Les attributs de cookie sécurisés
Une grande partie de la sécurité des sessions vient du fait de donner au cookie de session les bons attributs. Vous les définissez avec session_set_cookie_params() avant l'appel à session_start(). Trois attributs sont critiques :
<?php
session_set_cookie_params([
'lifetime' => 0, // se termine à la fermeture du navigateur
'path' => '/',
'secure' => true, // uniquement en HTTPS
'httponly' => true, // inaccessible au JavaScript
'samesite' => 'Lax', // protection contre le CSRF
]);
session_start();
- Secure : le cookie n'est envoyé que sur une connexion HTTPS. Cela empêche le vol du session ID via du HTTP en clair.
- HttpOnly : le cookie n'est pas accessible depuis JavaScript via
document.cookie. Même en présence d'une faille XSS, cela rend le vol du session ID bien plus difficile. - SameSite : contrôle si le cookie est envoyé sur les requêtes provenant d'autres sites.
Laxest un bon équilibre pour la plupart des applications ;Strictest plus restrictif.
Se défendre contre la fixation de session
Une attaque par fixation de session consiste à faire utiliser à la victime un session ID que l'attaquant connaît déjà. Quand la victime se connecte avec cet identifiant, l'attaquant s'introduit dans la session avec le même identifiant. La solution est simple mais essentielle : régénérer le session ID dès que le niveau de privilège change. Autrement dit, appelez session_regenerate_id() au moment où l'utilisateur se connecte.
<?php
// APRÈS la vérification du mot de passe
if (password_verify($password, $hash)) {
// Invalider l'ancienne session, générer un nouvel ID
session_regenerate_id(true);
$_SESSION['user_id'] = $user['id'];
$_SESSION['logged_in'] = true;
}
L'argument true ici supprime aussi l'ancien fichier de session. Le même principe s'applique à l'élévation de privilèges, comme un utilisateur normal accédant à un panneau d'administration.
Fermer une session en toute sécurité
La déconnexion ne se termine pas en vidant simplement $_SESSION. Vous devez nettoyer à la fois les données sur le serveur et le cookie dans le navigateur. Une déconnexion complète ressemble à ceci :
<?php
session_start();
// 1. Vider les données de session
$_SESSION = [];
// 2. Supprimer le cookie de session
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 sur le serveur
session_destroy();
Oublier l'une de ces trois étapes est une erreur fréquente : si vous n'appelez que session_destroy(), un ancien cookie peut rester dans le navigateur ; si vous ne faites que $_SESSION = [], le fichier sur le serveur n'est pas supprimé.
Utiliser correctement vos propres cookies
Au-delà des sessions, vous pouvez utiliser des cookies directement pour des données non sensibles comme une préférence de langue ou de thème. À partir de PHP 7.3, setcookie() accepte ses options sous forme de tableau, ce qui permet de définir proprement des attributs modernes comme SameSite :
<?php
setcookie('theme', 'dark', [
'expires' => time() + 60 * 60 * 24 * 30, // 30 jours
'path' => '/',
'secure' => true,
'httponly' => false, // si le JS doit le lire
'samesite' => 'Lax',
]);
Souvenez-vous : la donnée que vous écrivez dans un cookie peut être modifiée par l'utilisateur. Ne basez donc jamais une décision de confiance du type « cet utilisateur est-il admin ? » sur une valeur de cookie. Les décisions d'autorisation doivent toujours s'appuyer sur la session côté serveur.
Questions fréquentes
Où sont stockées les données de session ?
Par défaut, dans un fichier d'un dossier temporaire sur le serveur. Le réglage session.save_path définit cet emplacement. Dans les applications qui montent en charge, il est courant de passer à un pilote de session basé sur Redis ou une base de données, afin que plusieurs serveurs voient la même session.
Combien de temps vit une session ?
Deux réglages l'influencent : session.gc_maxlifetime décide combien de temps les données restent valides sur le serveur, tandis que le lifetime du cookie décide combien de temps le navigateur conserve le session ID. Si vous voulez un véritable délai de déconnexion, le plus fiable est de stocker l'heure de dernière activité dans la session et de la vérifier vous-même.
Puis-je conserver des données sensibles dans un cookie ?
Non. Un cookie réside dans le navigateur en clair et peut être lu et modifié par l'utilisateur. Tout ce qui est mot de passe ou niveau de droits doit rester dans la session côté serveur ; un cookie ne doit transporter que le session ID impossible à deviner ou des préférences non sensibles.
Mettez en place une gestion de session correcte dès le départ. Si vous voulez sécuriser l'authentification d'un projet PHP existant ou construire une couche de session solide de zéro, contactez-moi et posons ensemble des fondations sûres.