📚 Fiche de Révision - Séance 12

Thème : Cookies, Sessions et Sécurité (Validation d'Inscription)

🍪 1. Les Cookies en PHP

Qu'est-ce qu'un Cookie ?

Un cookie est un petit fichier texte stocké sur l'ordinateur du client (navigateur) qui permet au serveur de stocker des informations et de les récupérer à chaque requête. Les cookies sont utiles pour maintenir une session ouverte, mémoriser les préférences utilisateur, ou implémenter une fonction "se souvenir de moi".

Créer un Cookie

Pour créer un cookie en PHP, utilisez la fonction setcookie() avant tout affichage HTML :

setcookie("nom_du_cookie", "valeur", time() + 3600, "/");

Durée de Vie

Expression Durée
time() + 3600 1 heure
time() + 24*3600 1 jour
time() + 31*24*3600 31 jours

Accéder à un Cookie

if (isset($_COOKIE["nom_du_cookie"])) {
    echo $_COOKIE["nom_du_cookie"];
}

Supprimer un Cookie

// Méthode 1 : unset
unset($_COOKIE["nom_du_cookie"]);

// Méthode 2 : Expiration immédiate (plus sûr)
setcookie("nom_du_cookie", "", time() - 3600, "/");
⚠️ Important : setcookie() doit être appelée avant toute sortie HTML, sinon elle génère une erreur.

🔐 2. Connexion Automatique avec Tokens

Concept "Se Souvenir de Moi"

Permet à l'utilisateur de rester connecté pendant une période prolongée (par ex. 31 jours) sans avoir à entrer ses identifiants à chaque visite.

Étapes de Création d'un Token

  1. Générer un token unique : Utilisez sha1() avec des données uniques (pseudonyme + clé secrète + timestamp)
  2. Stocker dans la BDD : Enregistrez le token dans le champ token_cookie
  3. Créer un cookie : Stockez le token côté client avec setcookie()

Exemple Complet

// 1. Générer le token
$token = sha1($pseudonyme . "secret_k3y" . time());

// 2. Mettre à jour la BDD
$sql = "UPDATE utilisateur SET token_cookie = ? WHERE pseudonyme = ?";
$request = BDD::get()->prepare($sql);
$request->execute([$token, $pseudonyme]);

// 3. Créer le cookie (expire dans 31 jours)
setcookie("token", $token, time() + 31*24*3600, "/");

Vérification à la Connexion

Dans votre fichier de démarrage de session (généralement en haut avec session_start()) :

// Vérifier si le cookie "token" existe
if (isset($_COOKIE["token"])) {
    // Chercher l'utilisateur avec ce token dans la BDD
    $sql = "SELECT * FROM utilisateur WHERE token_cookie = ?";
    $request = BDD::get()->prepare($sql);
    $request->execute([$_COOKIE["token"]]);
    
    if ($request->rowCount() > 0) {
        // Connecter automatiquement l'utilisateur
        $user = $request->fetch();
        $_SESSION["pseudonyme"] = $user["pseudonyme"];
    }
}

Suppression à la Déconnexion

// Dans logout.php
unset($_COOKIE["token"]);
setcookie("token", "", time() - 3600, "/");

// Optionnel : mettre à jour la BDD
$sql = "UPDATE utilisateur SET token_cookie = NULL WHERE pseudonyme = ?";
$request = BDD::get()->prepare($sql);
$request->execute([$_SESSION["pseudonyme"]]);
💡 Bonnes Pratiques :
  • Utilisez une clé secrète robuste (pas "secret_k3y" en production !)
  • Stockez le token hashé dans la BDD
  • Vérifiez toujours les tokens côté serveur
  • Utilisez HTTPS en production pour sécuriser la transmission

🤖 3. reCaptcha (Google Captcha)

Qu'est-ce que reCaptcha ?

reCaptcha est un service de Google qui vérifie que l'utilisateur est humain avant de soumettre un formulaire. Cela prévient les abus de robots.

Inscription à reCaptcha

Implémentation Front-End

Ajoutez le script Google et les attributs au bouton :

<script src="https://www.google.com/recaptcha/api.js" async defer></script>
<script>
    function onSubmit(token) {
      document.getElementById("signup_form").submit();
    }
</script>

<form id="signup_form">
    <button 
        class="g-recaptcha" 
        data-sitekey="VOTRE_SITE_KEY" 
        data-callback='onSubmit' 
        data-action='submit'>
        S'inscrire
    </button>
</form>

Implémentation Back-End (PHP)

// Récupérer la réponse du captcha
$recaptchaResponse = $_POST['g-recaptcha-response'] ?? '';
$secretKey = 'VOTRE_SECRET_KEY';

// Préparer la requête
$url = 'https://www.google.com/recaptcha/api/siteverify';
$data = [
    'secret' => $secretKey,
    'response' => $recaptchaResponse,
];

// Effectuer la requête POST
$options = [
    'http' => [
        'header'  => "Content-type: application/x-www-form-urlencoded\r\n",
        'method'  => 'POST',
        'content' => http_build_query($data),
    ],
];
$context = stream_context_create($options);
$response = file_get_contents($url, false, $context);
$result = json_decode($response, true);

// Vérifier le résultat
if (!($result['success'] ?? false)) {
    // Captcha échoué, rejeter l'inscription
    header("Location: login.php?error=captcha");
    exit;
}
⚠️ Important : Vérifiez TOUJOURS le captcha côté serveur (back-end). La vérification côté client peut être contournée.

✉️ 4. Validation par Email

Concept

Lors de l'inscription, créer un compte "inactif" et envoyer un email avec un lien contenant un code de validation. L'utilisateur doit cliquer sur ce lien pour activer son compte.

Étape 1 : Créer un Token de Validation

Lors de l'inscription, générez un token unique et stockez-le :

// Générer le token
$token_mail_validation = sha1("TOKEN_MAIL" . time() . $pseudonyme);

// Insérer l'utilisateur avec le token (compte inactif)
$sql = "INSERT INTO utilisateur(pseudonyme, mot_de_passe, token_mail_validation) 
        VALUES (?, ?, ?)";
$request = BDD::get()->prepare($sql);
$request->execute([$pseudonyme, password_hash($password, PASSWORD_BCRYPT), $token_mail_validation]);

Étape 2 : Envoyer l'Email

// Préparer le contenu HTML
$sitename = "Mon Site";
$siteurl = "http://monsite.local";
$message_html = "<html><body>" .
    "<p>Bonjour, votre compte a été créé. Cliquez ici pour l'activer :</p>" .
    "<a href='" . $siteurl . "/api/confirm_mail.php?code=" . $token_mail_validation . "'>" .
    "Activer mon compte</a>" .
    "</body></html>";

// En-têtes
$headers = "MIME-Version: 1.0\r\n";
$headers .= "Content-type: text/html; charset=utf-8\r\n";

// Envoyer
mail($email, "Validation de votre inscription", $message_html, $headers);

Étape 3 : Créer confirm_mail.php

Créez un fichier dans le dossier /api :

<?php
include "myBDD.php";

// Récupérer le code de validation
$code = $_GET["code"] ?? null;

if ($code) {
    // Chercher l'utilisateur avec ce code
    $sql = "SELECT * FROM utilisateur WHERE token_mail_validation = ?";
    $request = BDD::get()->prepare($sql);
    $request->execute([$code]);
    
    if ($request->rowCount() > 0) {
        // Valider le compte (mettre le token à NULL)
        $sql_update = "UPDATE utilisateur SET token_mail_validation = NULL WHERE token_mail_validation = ?";
        $request_update = BDD::get()->prepare($sql_update);
        $request_update->execute([$code]);
        
        // Rediriger
        header("Location: login.php?success=validation");
        exit;
    }
}

header("Location: login.php?error=code");
exit;
?>

Étape 4 : Modifier login.php

Vérifiez que le compte est activé avant de permettre la connexion :

// Dans login.php du dossier /api
$sql = "SELECT * FROM utilisateur 
        WHERE pseudonyme = ? AND token_mail_validation IS NULL";
$request = BDD::get()->prepare($sql);
$request->execute([$pseudonyme]);
✅ Résumé du Processus :
  1. Utilisateur s'inscrit → Token généré
  2. Email envoyé avec lien contenant le token
  3. Utilisateur clique sur le lien
  4. confirm_mail.php valide et supprime le token
  5. Utilisateur peut se connecter

🔒 5. Sécurité - Points Clés

Hachage des Mots de Passe : Utilisez password_hash() et password_verify(), jamais md5() ou sha1().
Tokens Uniques : Utilisez sha1() ou hash() avec des données changeantes (timestamp, microtime, etc.).
HTTPS : En production, utilisez HTTPS pour chiffrer la transmission des données et cookies.
Vérification Serveur : Ne faites jamais confiance à la vérification côté client. Validez TOUJOURS côté serveur.
Expiration des Tokens : Les tokens doivent avoir une durée de vie limitée (ex: 31 jours pour les cookies persistants).

📋 Résumé des Fichiers PHP à Modifier/Créer

Fichier Action Détail
login.php Modifier Créer token, setcookie, vérifier token_mail_validation IS NULL
logout.php Modifier Supprimer le cookie avec setcookie
session_start.php Modifier Vérifier et charger le cookie pour connexion auto
signup.php Modifier Ajouter reCaptcha, token_mail_validation, envoyer email
confirm_mail.php Créer Valider le compte (mettre token à NULL)