DEV Community

Cover image for Construire un système d'authentification PHP complet — de l'inscription à la session sécurisée
Soulaiman Joui
Soulaiman Joui

Posted on

Construire un système d'authentification PHP complet — de l'inscription à la session sécurisée

Dans cet article, vous apprendrez à construire un système d'authentification PHP complet : inscription, vérification d'email par token, connexion sécurisée avec bcrypt, protection des routes et gestion des sessions. Tout le code est disponible sur GitHub : https://github.com/soulaiman19/projetdephp

Introduction :
Presque chaque application web a besoin d'un système d'authentification. Plutôt que d'utiliser un framework, comprendre comment construire ce système from scratch vous donnera une base solide.Dans cet article, nous allons construire SocialBook — une mini application sociale en PHP pur avec :
Inscription avec validation et hachage du mot de passe.
Vérification d'email via un token unique.
Connexion sécurisée et gestion de session.
Protection des pages par middleware.

Prérequis :
PHP 8.0+
MySQL
Un serveur local (XAMPP)
Connaissance de base du PHP et HTML

1-Base de données — dbname.sql
Commençons par créer la base de données et la table users.

CREATE DATABASE IF NOT EXISTS app_php;
USE app_php;

CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL,
verified TINYINT DEFAULT 0,
verification_code VARCHAR(255),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE INDEX idx_email ON users(email);
CREATE INDEX idx_verified ON users(verified);

  1. Connexion PDO — db.php On utilise PDO pour une connexion sécurisée et portable. php<?php $host = 'localhost'; $dbname = 'app_php'; $user = 'root'; $pass = '';

try {
$pdo = new PDO(
"mysql:host=$host;dbname=$dbname;charset=utf8mb4",
$user, $pass
);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
die("Erreur DB : " . htmlspecialchars($e->getMessage()));
}

  1. Le cœur du système — auth.php Toute la logique métier est centralisée dans auth.php. 3.1 Vérification de session phpfunction isLoggedIn(): bool { return !empty($_SESSION['user']); }

function requireLogin(): void
{
if (!isLoggedIn()) {
header('Location: login.php');
exit;
}
}
3.2 Inscription — createUser()
phpfunction createUser(string $email, string $password): array
{
global $pdo;

if (getUser($email)) {
    return ['success' => false, 'message' => 'Ce compte existe déjà.'];
}

$code           = bin2hex(random_bytes(4));
$hashedPassword = password_hash($password, PASSWORD_DEFAULT);

$stmt = $pdo->prepare(
    "INSERT INTO users (email, password, verification_code, verified)
     VALUES (?, ?, ?, 0)"
);
$stmt->execute([$email, $hashedPassword, $code]);

return ['success' => true, 'code' => $code];
Enter fullscreen mode Exit fullscreen mode

}

3.3 Vérification d'email — verifyUserEmail()
phpfunction verifyUserEmail(string $email, string $code): bool
{
global $pdo;

$stmt = $pdo->prepare(
    "SELECT verification_code FROM users WHERE email = ?"
);
$stmt->execute([$email]);
$result = $stmt->fetch();

if (!$result || $result['verification_code'] !== $code) {
    return false;
}

$stmt = $pdo->prepare(
    "UPDATE users SET verified = 1, verification_code = NULL WHERE email = ?"
);
$stmt->execute([$email]);

return true;
Enter fullscreen mode Exit fullscreen mode

}
3.4 Authentification — authenticate()
phpfunction authenticate(string $email, string $password)
{
$user = getUser($email);

if (!$user || !password_verify($password, $user['password'])) {
    return null;
}
if (!$user['verified']) {
    return 'not_verified';
}

return $user;
Enter fullscreen mode Exit fullscreen mode

}

  1. Inscription — register.php
    phpif ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
    $password = trim($_POST['password'] ?? '');

    if (!$email) {
    $error = 'Email invalide.';
    } elseif (strlen($password) < 6) {
    $error = 'Mot de passe trop court (6 caractères min).';
    } else {
    $result = createUser($email, $password);
    if (!$result['success']) {
    $error = $result['message'];
    } else {
    $verificationLink = "verify_email.php?email="
    . urlencode($email)
    . "&code="
    . urlencode($result['code']);
    }
    }
    }

. Vérification email — verify_email.php
php$email = filter_input(INPUT_GET, 'email', FILTER_VALIDATE_EMAIL);
$code = $_GET['code'] ?? '';

if (!$email || !$code) {
$error = 'Lien invalide ou incomplet.';
} elseif (verifyUserEmail($email, $code)) {
$message = 'Email vérifié ! Vous pouvez vous connecter.';
} else {
$error = 'Code incorrect ou compte inexistant.';
}

  1. Connexion — login.php
    phpif ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
    $password = trim($_POST['password'] ?? '');

    $result = authenticate($email, $password);

    if ($result === null) {
    $error = 'Email ou mot de passe incorrect.';
    } elseif ($result === 'not_verified') {
    $error = 'Vérifiez votre email avant de vous connecter.';
    } else {
    loginUser($result);
    header('Location: home.php');
    exit;
    }
    }

  2. Protection des pages
    Chaque page réservée aux utilisateurs connectés commence par :
    php<?php
    require 'auth.php';
    requireLogin();
    $user = currentUser();
    ?>
    C'est le cas pour home.php, profile.php et dashboard.php. Si l'utilisateur n'est pas connecté, il est automatiquement redirigé vers login.php.

  3. Déconnexion — logout.php
    php<?php
    require 'auth.php';
    logout();
    header('Location: index.php');
    exit;

Bonnes pratiques & leçons apprises
Sécurité :

Toujours utiliser password_hash() + password_verify() — jamais MD5 ou SHA1

Utiliser des requêtes PDO préparées pour éviter les injections SQL

Appliquer htmlspecialchars() sur toutes les sorties HTML

Valider les emails avec FILTER_VALIDATE_EMAIL

Bloquer la connexion tant que l'email n'est pas vérifié

Architecture :

Séparer la logique métier (auth.php) de la présentation

Un seul fichier de fonctions d'auth — facile à tester et maintenir

Utiliser require en tête de chaque page protégée

À améliorer en production :

Envoyer le lien de vérification par email (PHPMailer)

Régénérer l'ID de session après connexion (session_regenerate_id(true))

Ajouter une expiration du token de vérification

Stocker les credentials DB dans .env

Conclusion :

Vous avez maintenant un système d'authentification PHP complet — inscription, vérification email, connexion sécurisée, protection des routes et déconnexion. Ce projet peut servir de base solide pour n'importe quelle application web PHP.
Le code source complet est disponible sur GitHub : https://github.com/soulaiman19/projetdephp

Top comments (0)