<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Soulaiman Joui</title>
    <description>The latest articles on DEV Community by Soulaiman Joui (@soulaiman19).</description>
    <link>https://dev.to/soulaiman19</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3891380%2Fc51220e2-76d5-4b44-96b6-3951d2a9e374.png</url>
      <title>DEV Community: Soulaiman Joui</title>
      <link>https://dev.to/soulaiman19</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/soulaiman19"/>
    <language>en</language>
    <item>
      <title>Construire un système d'authentification PHP complet — de l'inscription à la session sécurisée</title>
      <dc:creator>Soulaiman Joui</dc:creator>
      <pubDate>Tue, 21 Apr 2026 22:02:39 +0000</pubDate>
      <link>https://dev.to/soulaiman19/construire-un-systeme-dauthentification-php-complet-de-linscription-a-la-session-securisee-2mkk</link>
      <guid>https://dev.to/soulaiman19/construire-un-systeme-dauthentification-php-complet-de-linscription-a-la-session-securisee-2mkk</guid>
      <description>&lt;p&gt;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 : &lt;a href="https://github.com/soulaiman19/projetdephp" rel="noopener noreferrer"&gt;https://github.com/soulaiman19/projetdephp&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Introduction : &lt;br&gt;
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 :&lt;br&gt;
Inscription avec validation et hachage du mot de passe.&lt;br&gt;
Vérification d'email via un token unique.&lt;br&gt;
Connexion sécurisée et gestion de session.&lt;br&gt;
Protection des pages par middleware.&lt;/p&gt;

&lt;p&gt;Prérequis :&lt;br&gt;
PHP 8.0+&lt;br&gt;
MySQL &lt;br&gt;
Un serveur local (XAMPP)&lt;br&gt;
Connaissance de base du PHP et HTML&lt;/p&gt;

&lt;p&gt;1-Base de données — dbname.sql&lt;br&gt;
Commençons par créer la base de données et la table users.&lt;/p&gt;

&lt;p&gt;CREATE DATABASE IF NOT EXISTS app_php;&lt;br&gt;
USE app_php;&lt;/p&gt;

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

&lt;p&gt;CREATE INDEX idx_email ON users(email);&lt;br&gt;
CREATE INDEX idx_verified ON users(verified);&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Connexion PDO — db.php
On utilise PDO pour une connexion sécurisée et portable.
php&amp;lt;?php
$host   = 'localhost';
$dbname = 'app_php';
$user   = 'root';
$pass   = '';&lt;/li&gt;
&lt;/ol&gt;

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

&lt;ol&gt;
&lt;li&gt;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']);
}&lt;/li&gt;
&lt;/ol&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (getUser($email)) {
    return ['success' =&amp;gt; false, 'message' =&amp;gt; 'Ce compte existe déjà.'];
}

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

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

return ['success' =&amp;gt; true, 'code' =&amp;gt; $code];
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;/p&gt;

&lt;p&gt;3.3 Vérification d'email — verifyUserEmail()&lt;br&gt;
phpfunction verifyUserEmail(string $email, string $code): bool&lt;br&gt;
{&lt;br&gt;
    global $pdo;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$stmt = $pdo-&amp;gt;prepare(
    "SELECT verification_code FROM users WHERE email = ?"
);
$stmt-&amp;gt;execute([$email]);
$result = $stmt-&amp;gt;fetch();

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

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

return true;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;br&gt;
3.4 Authentification — authenticate()&lt;br&gt;
phpfunction authenticate(string $email, string $password)&lt;br&gt;
{&lt;br&gt;
    $user = getUser($email);&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (!$user || !password_verify($password, $user['password'])) {
    return null;
}
if (!$user['verified']) {
    return 'not_verified';
}

return $user;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Inscription — register.php&lt;br&gt;
phpif ($_SERVER['REQUEST_METHOD'] === 'POST') {&lt;br&gt;
$email    = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);&lt;br&gt;
$password = trim($_POST['password'] ?? '');&lt;/p&gt;

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

&lt;p&gt;. Vérification email — verify_email.php&lt;br&gt;
php$email = filter_input(INPUT_GET, 'email', FILTER_VALIDATE_EMAIL);&lt;br&gt;
$code  = $_GET['code'] ?? '';&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Connexion — login.php&lt;br&gt;
phpif ($_SERVER['REQUEST_METHOD'] === 'POST') {&lt;br&gt;
$email    = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);&lt;br&gt;
$password = trim($_POST['password'] ?? '');&lt;/p&gt;

&lt;p&gt;$result = authenticate($email, $password);&lt;/p&gt;

&lt;p&gt;if ($result === null) {&lt;br&gt;
    $error = 'Email ou mot de passe incorrect.';&lt;br&gt;
} elseif ($result === 'not_verified') {&lt;br&gt;
    $error = 'Vérifiez votre email avant de vous connecter.';&lt;br&gt;
} else {&lt;br&gt;
    loginUser($result);&lt;br&gt;
    header('Location: home.php');&lt;br&gt;
    exit;&lt;br&gt;
}&lt;br&gt;
}&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Protection des pages&lt;br&gt;
Chaque page réservée aux utilisateurs connectés commence par :&lt;br&gt;
php&amp;lt;?php&lt;br&gt;
require 'auth.php';&lt;br&gt;
requireLogin();&lt;br&gt;
$user = currentUser();&lt;br&gt;
?&amp;gt;&lt;br&gt;
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.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Déconnexion — logout.php&lt;br&gt;
php&amp;lt;?php&lt;br&gt;
require 'auth.php';&lt;br&gt;
logout();&lt;br&gt;
header('Location: index.php');&lt;br&gt;
exit;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Bonnes pratiques &amp;amp; leçons apprises&lt;br&gt;
Sécurité :&lt;/p&gt;

&lt;p&gt;Toujours utiliser password_hash() + password_verify() — jamais MD5 ou SHA1&lt;/p&gt;

&lt;p&gt;Utiliser des requêtes PDO préparées pour éviter les injections SQL&lt;/p&gt;

&lt;p&gt;Appliquer htmlspecialchars() sur toutes les sorties HTML&lt;/p&gt;

&lt;p&gt;Valider les emails avec FILTER_VALIDATE_EMAIL&lt;/p&gt;

&lt;p&gt;Bloquer la connexion tant que l'email n'est pas vérifié&lt;/p&gt;

&lt;p&gt;Architecture :&lt;/p&gt;

&lt;p&gt;Séparer la logique métier (auth.php) de la présentation&lt;/p&gt;

&lt;p&gt;Un seul fichier de fonctions d'auth — facile à tester et maintenir&lt;/p&gt;

&lt;p&gt;Utiliser require en tête de chaque page protégée&lt;/p&gt;

&lt;p&gt;À améliorer en production :&lt;/p&gt;

&lt;p&gt;Envoyer le lien de vérification par email (PHPMailer)&lt;/p&gt;

&lt;p&gt;Régénérer l'ID de session après connexion (session_regenerate_id(true))&lt;/p&gt;

&lt;p&gt;Ajouter une expiration du token de vérification&lt;/p&gt;

&lt;p&gt;Stocker les credentials DB dans .env&lt;/p&gt;

&lt;p&gt;Conclusion : &lt;/p&gt;

&lt;p&gt;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.&lt;br&gt;
Le code source complet est disponible sur GitHub : &lt;a href="https://github.com/soulaiman19/projetdephp" rel="noopener noreferrer"&gt;https://github.com/soulaiman19/projetdephp&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>php</category>
      <category>mysql</category>
      <category>authentication</category>
    </item>
  </channel>
</rss>
