Leçon 14 / 18

Protéger l’accès par mot de passe

35 min PHP 8 — premiers scripts et formulaires Gratuit

Objectif : Restreindre les pages du carnet à une personne authentifiée.

Une page masquée dans la navigation reste accessible si son adresse est connue. Pour protéger le carnet, vous devez donc vérifier l’authentification sur chaque page privée, avant d’envoyer le moindre HTML au navigateur.

Vous allez enregistrer dans la session un état d’authentification, et non le mot de passe lui-même. Le formulaire de connexion comparera le mot de passe envoyé à un hachage configuré sur le serveur. Les pages privées consulteront ensuite la session avant de poursuivre leur traitement.

Configurer les fonctions d’authentification

Ajoutez ces fonctions à includes/fonctions.php, en conservant les fonctions déjà utilisées par le carnet. Le démarrage de session doit avoir lieu avant toute sortie HTML. Les options proposées empêchent notamment l’accès au cookie depuis JavaScript et limitent son envoi aux échanges HTTPS lorsque le site est déployé avec HTTPS.

PHP
<?php

declare(strict_types=1);

function demarrer_session(): void
{
    if (session_status() === PHP_SESSION_ACTIVE) {
        return;
    }

    $https_actif = isset($_SERVER['HTTPS'])
        && $_SERVER['HTTPS'] !== 'off';

    session_set_cookie_params([
        'httponly' => true,
        'secure' => $https_actif,
        'samesite' => 'Lax',
    ]);

    session_start();
}

function est_connecte(): bool
{
    return ($_SESSION['authentifie'] ?? false) === true;
}

function exiger_authentification(): void
{
    demarrer_session();

    if (!est_connecte()) {
        header('Location: connexion.php', true, 302);
        exit;
    }
}

function verifier_mot_de_passe(string $mot_de_passe): bool
{
    $hachage = getenv('CARNET_MOT_DE_PASSE_HASH');

    return $hachage !== false
        && $hachage !== ''
        && password_verify($mot_de_passe, $hachage);
}

La fonction exiger_authentification() interrompt la requête avec exit après la redirection : le code privé ne s’exécute donc pas pour une personne non connectée. Configurez la variable d’environnement CARNET_MOT_DE_PASSE_HASH sur le serveur avec le hachage du mot de passe, jamais avec le mot de passe en clair.

Traiter la connexion avant l’affichage

Dans connexion.php, chargez les fonctions et traitez la requête avant d’inclure l’en-tête commun. Ce fichier complet affiche le formulaire lors d’une visite normale et un message d’erreur si le mot de passe reçu ne correspond pas au hachage configuré. Il utilise la classe carnet-connexion et conserve les inclusions communes du projet.

PHP
<?php

declare(strict_types=1);

require __DIR__ . '/includes/fonctions.php';

demarrer_session();
$erreur = '';

if (($_SERVER['REQUEST_METHOD'] ?? '') === 'POST') {
    $mot_de_passe = $_POST['mot_de_passe'] ?? '';

    if (is_string($mot_de_passe) && verifier_mot_de_passe($mot_de_passe)) {
        session_regenerate_id(true);
        $_SESSION['authentifie'] = true;
        header('Location: index.php', true, 302);
        exit;
    }

    $erreur = 'Le mot de passe est incorrect.';
}

require __DIR__ . '/includes/entete.php';
?>
<main class="carnet-principal">
  <section aria-labelledby="titre-connexion">
    <h2 id="titre-connexion">Accès privé</h2>
    <?php if ($erreur !== ''): ?>
      <p class="carnet-message carnet-message--erreur" role="alert">
        <?= htmlspecialchars($erreur, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') ?>
      </p>
    <?php endif; ?>
    <form class="carnet-connexion" action="connexion.php" method="post">
      <label class="carnet-champ" for="mot-de-passe">Mot de passe</label>
      <input id="mot-de-passe" name="mot_de_passe" type="password" required>
      <div class="carnet-actions">
        <button type="submit">Se connecter</button>
      </div>
    </form>
  </section>
</main>
<?php require __DIR__ . '/includes/pied.php'; ?>

Après une vérification réussie, session_regenerate_id(true) remplace l’identifiant de session avant d’enregistrer l’état connecté. Cela réduit le risque qu’un identifiant de session connu avant la connexion soit réutilisé. Le navigateur est ensuite redirigé vers index.php ; une soumission invalide reste sur le formulaire et reçoit une erreur générique.

Protéger chaque page privée

Dans index.php et contact-ajouter.php, appelez exiger_authentification() tout en haut du fichier, avant le traitement, l’en-tête ou tout autre affichage. Appliquez le même contrôle aux pages privées dès leur création, notamment celles de modification, de suppression et de recherche. La navigation n’est pas une protection : chaque script doit effectuer son propre contrôle côté serveur.

PHP
<?php

declare(strict_types=1);

require __DIR__ . '/includes/fonctions.php';

exiger_authentification();

// Le traitement existant de la page commence ensuite.

À retenir

  • Stockez le hachage du mot de passe dans la configuration du serveur, pas le mot de passe en clair dans le projet.
  • Vérifiez le mot de passe avec password_verify et ne placez dans la session qu’un état d’authentification.
  • Régénérez l’identifiant de session après une connexion réussie.
  • Contrôlez l’accès au début de chaque page privée, avant tout traitement ou affichage.

La prochaine leçon portera sur la protection des opérations qui modifient les données du carnet.

Envie d'aller plus loin ?

Les cours Enovatic sont gratuits et le resteront. Si vous cherchez un accompagnement encadré, nos formations professionnelles sont animées par les mêmes formateurs.