aslain.dev
0%
01 Hizmetler 02 Hakkımda 03 Projeler 04 Stack 05 Blog 06 İletişim
← Tüm makaleler Metin2

Système d'inscription Metin2 : un formulaire PHP sécurisé

Quand tu lances un serveur Metin2, la première porte que les joueurs franchissent est le formulaire d'inscription de ton site. Un bon système d'inscription Metin2 ne se contente pas de récupérer un identifiant et un mot de passe : il valide les entrées, stocke le mot de passe dans le format exact attendu par le jeu et écrit en toute sécurité dans la table account. Dans ce guide, on construit de zéro un flux d'inscription fonctionnel et à l'épreuve des injections, avec PHP et PDO.

Comment fonctionne la table account

Dans les sources classiques de Metin2, les données d'adhésion vivent dans la table account au sein d'une base de données appelée account. Le cœur du jeu (les processus game et db) authentifie les connexions directement sur cette table. Les colonnes qui nous intéressent sont :

  • login — le nom d'utilisateur (généralement court et unique).
  • password — le champ que le jeu lit. La source classique attend le hash de 41 caractères produit par la fonction PASSWORD() de MySQL.
  • social_id — un code de sécurité à 7 chiffres (un second mot de passe) utilisé pour des actions comme la suppression de personnages.
  • email et create_time — les coordonnées et l'heure d'inscription.

Un détail crucial : la fonction PASSWORD() a été supprimée dans MySQL 8.0. La plupart des serveurs Metin2 tournent sous MariaDB ou MySQL 5.x, donc la fonction existe encore, mais tu dois vérifier ta version. Tu es obligé de stocker le mot de passe avec le même algorithme que le cœur du jeu — sinon un joueur inscrit sur le web ne pourra pas se connecter au jeu.

Une connexion sécurisée à la base de données

Avant tout, utilise PDO avec des requêtes préparées. En séparant l'entrée utilisateur de la requête, tu bloques l'injection SQL à la racine. Garde la connexion dans un fichier config.php séparé :

<?php
// config.php
$host = '127.0.0.1';
$db   = 'account';
$user = 'metin2_web';      // utilisateur ayant des droits uniquement sur la table account
$pass = 'MOT_DE_PASSE_FORT';

$dsn = "mysql:host=$host;dbname=$db;charset=utf8mb4";
$pdo = new PDO($dsn, $user, $pass, [
    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    PDO::ATTR_EMULATE_PREPARES   => false,
]);

Crée un utilisateur MySQL dédié au web et accorde-lui seulement les privilèges nécessaires sur account.account. Même si le serveur web est compromis, l'attaquant ne doit pas atteindre toute ta base de données de jeu.

Le formulaire d'inscription et la validation des entrées

Commence par un formulaire HTML simple mais suffisant. Le vrai travail consiste à valider les données entrantes côté serveur — ne fais jamais confiance aux vérifications côté client.

<form method="post" action="register.php">
  <input name="login" placeholder="Identifiant" required>
  <input name="email" type="email" placeholder="E-mail" required>
  <input name="password" type="password" placeholder="Mot de passe" required>
  <input name="password2" type="password" placeholder="Répéter le mot de passe" required>
  <input type="hidden" name="csrf" value="<?= $_SESSION['csrf'] ?>">
  <button type="submit">S'inscrire</button>
</form>

Côté serveur, vérifie chaque champ un par un :

<?php
session_start();
require 'config.php';

// Vérification CSRF
if (!hash_equals($_SESSION['csrf'] ?? '', $_POST['csrf'] ?? '')) {
    http_response_code(400);
    exit('Requête invalide.');
}

$login = trim($_POST['login'] ?? '');
$email = trim($_POST['email'] ?? '');
$pw    = $_POST['password'] ?? '';
$pw2   = $_POST['password2'] ?? '';
$errors = [];

if (!preg_match('/^[a-zA-Z0-9]{4,16}$/', $login)) {
    $errors[] = 'L\'identifiant doit faire 4-16 lettres/chiffres uniquement.';
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
    $errors[] = 'Saisis une adresse e-mail valide.';
}
if (strlen($pw) < 6 || $pw !== $pw2) {
    $errors[] = 'Le mot de passe doit faire au moins 6 caractères et les deux champs doivent correspondre.';
}

Restreindre login à un motif strict (lettres et chiffres uniquement) évite à la fois les problèmes de compatibilité avec le client du jeu et les caractères inattendus.

Vérifie les collisions de nom d'utilisateur

Pour empêcher deux personnes de s'inscrire avec le même identifiant, interroge la base avant d'écrire. Utilise aussi une requête préparée ici :

if (!$errors) {
    $stmt = $pdo->prepare('SELECT id FROM account WHERE login = ? LIMIT 1');
    $stmt->execute([$login]);
    if ($stmt->fetch()) {
        $errors[] = 'Cet identifiant est déjà pris.';
    }
}

Pour autant, n'en fais pas ta seule ligne de défense : ajoute un index UNIQUE sur la colonne login de la table account. Si deux requêtes arrivent au même instant, la contrainte au niveau de la base bloque le doublon.

Hache le mot de passe et écris dans la table account

À la dernière étape, on crée l'enregistrement. Hacher le mot de passe directement dans le SQL avec PASSWORD() garantit le format attendu par le jeu. Génère un code aléatoire à 7 chiffres pour social_id :

if (!$errors) {
    $social = sprintf('%07d', random_int(0, 9999999));

    $sql = 'INSERT INTO account (login, password, social_id, email, create_time)
            VALUES (?, PASSWORD(?), ?, ?, NOW())';
    $stmt = $pdo->prepare($sql);
    $stmt->execute([$login, $pw, $social, $email]);

    header('Location: register.php?ok=1');
    exit;
}

Remarque qu'on passe le mot de passe en clair comme paramètre et qu'on laisse MySQL faire le hachage. Cela préserve la sécurité des requêtes préparées tout en rendant le hash compatible octet par octet avec le jeu. Si tu haches toi-même le mot de passe en PHP (par exemple avec password_hash()) et que tu stockes ce résultat, le cœur du jeu ne le reconnaîtra pas — une erreur très fréquente. password_hash()/bcrypt n'a de sens que si tu construis un système de comptes purement web, indépendant du jeu.

Avant la mise en production

Une fois le flux fonctionnel, ajoute ces couches de sécurité :

  • Limitation de débit : bloque plus de quelques inscriptions par minute depuis la même IP pour ralentir les bots.
  • HTTPS obligatoire : les mots de passe ne doivent jamais circuler en clair.
  • CAPTCHA : ajoute hCaptcha/reCAPTCHA contre les inscriptions automatisées.
  • Masquage des erreurs : ne montre jamais d'erreurs techniques à l'utilisateur ; journalise les détails côté serveur.

Questions fréquentes

Pourquoi hacher le mot de passe dans MySQL plutôt qu'en PHP ?

Parce que le cœur du jeu Metin2 compare le mot de passe de connexion au hash produit par la fonction PASSWORD() de MySQL. Si tu n'utilises pas le même algorithme, un joueur inscrit sur le web ne pourra pas entrer dans le jeu. Sauf si ton web et ton jeu sont des systèmes séparés, la correspondance est obligatoire.

Que faire si mon serveur n'a pas la fonction PASSWORD() ?

MySQL 8.0 l'a supprimée. La solution est de passer à MariaDB ou MySQL 5.7 (que la plupart des installations Metin2 utilisent déjà), ou de mapper le hash supporté par ton cœur (certains forks fournissent des schémas modifiés). Dans tous les cas, la référence est le code d'authentification de ton cœur de jeu.

À quoi sert social_id, puis-je le laisser vide ?

social_id est le code de sécurité en jeu (un second mot de passe), demandé lors d'actions critiques comme la suppression d'un personnage. Plutôt que de le laisser vide, l'approche la plus sûre est d'attribuer une valeur aléatoire à l'inscription et de laisser le joueur la changer depuis son panneau.

Besoin d'une inscription sécurisée et d'un panneau de compte pour ton serveur Metin2 ? Je peux le construire de bout en bout avec validation, confirmation par e-mail et intégration au panneau — contacte-moi.

Bu kategorideki tüm yazılar →

Devamı için