AzDev

VII - Cookies & Sessions dans Express.js

Les cookies permettent de stocker des informations directement dans le navigateur de l'utilisateur. À chaque requête, ces informations sont automatiquement envoyées au serveur. Les sessions, quant à elles, reposent sur un unique cookie contenant un identifiant de session, qui permet d'associer des données stockées côté serveur, sans limite de quantité. Dans ce chapitre, nous explorerons l'utilisation des cookies et des sessions avec Express.js, puis nous construirons une application pratique intégrant un système d'authentification simple.

Publié le
VII - Cookies & Sessions dans Express.js

1. Les Cookies avec Express.js

Les cookies sont de petits morceaux de données envoyés dans une réponse HTTP avec l'netête set-cookie et stockés côté client par le navigateur. Après quoi, toutes les requêtes suivantes enveront ce cookie dans l'entête HTTP cookie. Dans Express.js, nous pouvons facilement gérer les cookies grâce au middleware cookie-parser. Ce chapitre présente les bases des cookies et une démonstration simple.

1.1. Concepts de base

  • Les cookies sont envoyés avec chaque requête HTTP vers le serveur qui les a créés
  • Ils peuvent avoir des options comme :
    • maxAge : durée de vie en millisecondes
    • expires : date d'expiration
    • httpOnly : accessible uniquement via HTTP (pas JavaScript)
    • secure : envoyé uniquement via HTTPS

1.2. Comment ça marche

Explication :

  • Le client envoie une requête initiale, le serveur répond avec un cookie.
  • Les requêtes suivantes incluent le cookie dans l'en-tête, et le serveur peut le mettre à jour.
  • Une action explicite comme celle de la route (/clear) supprime le cookie.

1.3. Démonstration simple

Voici une démo qui :

  • Définit un cookie lorsqu'un utilisateur visite la page
  • Affiche le contenu du cookie
  • Permet de supprimer le cookie

Code du serveur (server.js)

1const express = require('express');
2const cookieParser = require('cookie-parser');
3const path = require('path');
4const app = express();
5const port = 3000;
6
7// Middleware
8app.use(express.static(path.join(__dirname, 'public')));
9app.use(cookieParser());
10
11// Routes
12app.get('/', (req, res) => {
13  // Vérifie si le cookie existe
14  if (!req.cookies.visitCount) {
15    res.cookie('visitCount', 1, { 
16      maxAge: 1000 * 60 * 60, // 1 heure
17      httpOnly: true 
18    });
19    res.sendFile(path.join(__dirname, 'public', 'index.html'));
20  } else {
21    // Incrémente le compteur
22    const count = parseInt(req.cookies.visitCount) + 1;
23    res.cookie('visitCount', count, { 
24      maxAge: 1000 * 60 * 60,
25      httpOnly: true 
26    });
27    res.send(`
28      <h1>Bienvenue!</h1>
29      <p>Nombre de visites: ${count}</p>
30      <a href="/clear">Effacer le cookie</a>
31    `);
32  }
33});
34
35app.get('/clear', (req, res) => {
36  res.clearCookie('visitCount');
37  res.redirect('/');
38});
39
40// Démarrage du serveur
41app.listen(port, () => {
42  console.log(`Serveur démarré sur http://localhost:${port}`);
43});

Fichier HTML (public/index.html)

1<!DOCTYPE html>
2<html>
3<head>
4  <title>Demo Cookies</title>
5</head>
6<body>
7  <h1>Bienvenue!</h1>
8  <p>C'est votre première visite!</p>
9  <p>Actualisez la page pour voir le compteur augmenter.</p>
10</body>
11</html>

Instructions d'installation

  1. Créez un nouveau dossier pour le projet
  2. Initialisez un projet npm : npm init -y
  3. Installez les dépendances : npm install express cookie-parser
  4. Créez un dossier public/ et ajoutez index.html
  5. Créez server.js avec le code ci-dessus
  6. Lancez le serveur : node server.js

Explications

Middleware

  • cookie-parser : Parse les cookies des requêtes et les rend disponibles dans req.cookies

  • express.static : Sert les fichiers statiques du dossier public

Fonctionnement

  1. À la première visite, un cookie visitCount est créé avec la valeur 1

  2. À chaque visite suivante :

    • Le cookie est lu via req.cookies.visitCount

    • La valeur est incrémentée

    • Un nouveau cookie est défini avec res.cookie()

La route /clear supprime le cookie avec res.clearCookie()

Options des cookies

  • maxAge : 1000 * 60 * 60 : Le cookie expire après 1 heure

  • httpOnly : true : Protège contre les attaques XSS en rendant le cookie inaccessible via JavaScript

1.4. Points pédagogiques

  1. Création : res.cookie(name, value, options)

  2. Lecture : req.cookies.name (avec cookie-parser)

  3. Suppression : res.clearCookie(name)

  4. Sécurité : Utilisation de httpOnly et éventuellement secure en production

2. Les Sessions avec Express.js (express-session)

Les sessions permettent de maintenir un état entre plusieurs requêtes HTTP en stockant des données côté serveur, associées à un identifiant unique envoyé au client via un cookie. Le package express-session est une solution populaire pour gérer les sessions dans Express.js. Ce chapitre explique les bases et propose une démonstration.

2.1. Concepts de base

  • Les données de session sont stockées côté serveur
  • Un cookie contenant un ID de session (par défaut connect.sid) est envoyé au client
  • Options importantes :
    • secret : clé pour signer le cookie
    • resave : force la sauvegarde de la session
    • saveUninitialized : sauvegarde des sessions non initialisées
    • cookie : options du cookie (maxAge, httpOnly, etc.)

2.2. Interactions entre le client et le serveur

Ce diagramme illustre comment une session est créée et maintenue avec express-session.

Explication :

  • Le serveur crée une session et envoie un ID via un cookie (connect.sid).
  • Les données (comme visitCount) sont stockées côté serveur, liées à cet ID.
  • La destruction de la session supprime les données serveur et invalide le cookie.

2.4. Démonstration simple

Cette démo :

  • Crée une session pour suivre le nombre de visites
  • Affiche les données de la session
  • Permet de détruire la session

Code du serveur (server.js)

1const express = require('express');
2const session = require('express-session');
3const path = require('path');
4const app = express();
5const port = 3000;
6
7// Middleware
8app.use(express.static(path.join(__dirname, 'public')));
9app.use(session({
10  secret: 'ma_cle_secrete',
11  resave: false,
12  saveUninitialized: false,
13  cookie: { 
14    maxAge: 1000 * 60 * 60, // 1 heure
15    httpOnly: true 
16  }
17}));
18
19// Routes
20app.get('/', (req, res) => {
21  // Initialise ou incrémente le compteur de visites
22  if (!req.session.visitCount) {
23    req.session.visitCount = 1;
24    res.sendFile(path.join(__dirname, 'public', 'index.html'));
25  } else {
26    req.session.visitCount += 1;
27    res.send(`
28      <h1>Bienvenue!</h1>
29      <p>Nombre de visites: ${req.session.visitCount}</p>
30      <a href="/destroy">Détruire la session</a>
31    `);
32  }
33});
34
35app.get('/destroy', (req, res) => {
36  req.session.destroy((err) => {
37    if (err) {
38      console.log(err);
39    }
40    res.redirect('/');
41  });
42});
43
44// Démarrage du serveur
45app.listen(port, () => {
46  console.log(`Serveur démarré sur http://localhost:${port}`);
47});

Fichier HTML (public/index.html)

1<!DOCTYPE html>
2<html>
3<head>
4  <title>Demo Sessions</title>
5</head>
6<body>
7  <h1>Bienvenue!</h1>
8  <p>C'est votre première visite!</p>
9  <p>Actualisez la page pour voir le compteur augmenter.</p>
10</body>
11</html>

Instructions d'installation

  1. Créez un nouveau dossier pour le projet

  2. Initialisez un projet npm : npm init -y

  3. Installez les dépendances : npm install express express-session

  4. Créez un dossier public/ et ajoutez index.html

  5. Créez server.js avec le code ci-dessus

  6. Lancez le serveur : node server.js

Explications

Middleware

  • express-session : Gère les sessions et crée req.session

  • express.static : Sert les fichiers statiques du dossier public

Fonctionnement

  1. À la première visite, req.session.visitCount est initialisé à 1
  2. À chaque visite suivante :
    • La valeur de visitCount est incrémentée dans la session
    • Les données sont automatiquement sauvegardées côté serveur
  3. L'option /destroy appelle req.session.destroy() pour supprimer la session

Configuration

  1. secret: 'ma_cle_secrete' : Signe le cookie pour la sécurité

  2. resave: false : Évite de sauvegarder la session si elle n'est pas modifiée

  3. saveUninitialized: false : Ne crée pas de session vide

  4. cookie.maxAge : Définit la durée de vie à 1 heure

2.5 Points pédagogiques

  1. Création/Modification : req.session.key = value

  2. Accès : req.session.key

  3. Destruction : req.session.destroy(callback)

  4. Stockage : Par défaut en mémoire memoryStore (non adapté à la production ). Les cookies peuvent être stockés dans des fichiers, des bases de données. Voir la documentation de express-session tout en bas de la page

2.6. Différence avec les cookies simples

  • Les cookies stockent les données côté client

  • Les sessions stockent les données côté serveur, seul l'ID est envoyé au client

3. Démonstration d'authentification avec Express.js

Voici une démonstration simple d'authentification utilisant Express.js avec des cookies et des sessions.

3.1. Code du serveur (server.js)

1const express = require('express');
2const session = require('express-session');
3const path = require('path');
4const app = express();
5const port = 3000;
6
7// Base de données factice (en mémoire)
8const users = [
9  { id: 1, username: 'admin', password: '1234' },
10  { id: 2, username: 'user', password: '5678' }
11];
12
13// Configuration du middleware
14app.use(express.urlencoded({ extended: true })); // Pour parser les formulaires
15app.use(express.static(path.join(__dirname, 'public'))); // Fichiers statiques
16app.use(session({
17  secret: 'ma_cle_secrete',
18  resave: false,
19  saveUninitialized: false,
20  cookie: { maxAge: 1000 * 60 * 60 } // 1 heure
21}));
22
23// Middleware pour vérifier si l'utilisateur est authentifié
24function isAuthenticated(req, res, next) {
25  if (req.session.user) {
26    next();
27  } else {
28    res.redirect('/login');
29  }
30}
31
32// Routes
33app.get('/', (req, res) => {
34  res.sendFile(path.join(__dirname, 'public', 'index.html'));
35});
36
37app.get('/login', (req, res) => {
38  res.sendFile(path.join(__dirname, 'public', 'login.html'));
39});
40
41app.post('/login', (req, res) => {
42  const { username, password } = req.body;
43  
44  const user = users.find(u => 
45    u.username === username && u.password === password
46  );
47
48  if (user) {
49    req.session.user = user;
50    res.redirect('/dashboard');
51  } else {
52    res.send('Identifiants incorrects. <a href="/login">Réessayer</a>');
53  }
54});
55
56app.get('/dashboard', isAuthenticated, (req, res) => {
57  res.send(`
58    <h1>Bienvenue ${req.session.user.username}!</h1>
59    <p>Ceci est votre tableau de bord</p>
60    <a href="/logout">Se déconnecter</a>
61  `);
62});
63
64app.get('/logout', (req, res) => {
65  req.session.destroy();
66  res.redirect('/login');
67});
68
69// Démarrage du serveur
70app.listen(port, () => {
71  console.log(`Serveur démarré sur http://localhost:${port}`);
72});

Et voici les fichiers HTML nécessaires dans le dossier public/ :

1<!-- public/index.html -->
2<!DOCTYPE html>
3<html>
4<head>
5  <title>Accueil</title>
6</head>
7<body>
8  <h1>Bienvenue sur notre site</h1>
9  <a href="/login">Se connecter</a>
10</body>
11</html>
1<!-- public/login.html -->
2<!DOCTYPE html>
3<html>
4<head>
5  <title>Connexion</title>
6</head>
7<body>
8  <h1>Connexion</h1>
9  <form method="POST" action="/login">
10    <div>
11      <label>Nom d'utilisateur:</label>
12      <input type="text" name="username" required>
13    </div>
14    <div>
15      <label>Mot de passe:</label>
16      <input type="password" name="password" required>
17    </div>
18    <button type="submit">Se connecter</button>
19  </form>
20</body>
21</html>

3.2. Pour exécuter cette démo :

  1. Créez un nouveau dossier pour le projet

  2. Initialisez un projet npm : npm init -y

  3. Installez les dépendances : npm install express express-session

  4. Créez un dossier public/ et placez-y les fichiers HTML

  5. Créez server.js avec le code ci-dessus

  6. Lancez le serveur : node server.js

3.3. Interactions entre le client et le serveur :

3.4. Points pédagogiques :

  1. Middleware :

    • express.static() sert les fichiers publics

    • express-session gère les sessions avec cookies

    • isAuthenticated protège les routes privées

  2. Flux d'authentification :

    • Formulaire POST vers /login

    • Vérification des identifiants

    • Création de la session

    • Redirection vers le dashboard

  3. Gestion de la session :

    • Stockage des données utilisateur dans req.session

    • Destruction de la session à la déconnexion

    • Expiration du cookie configurable