Salut,
mon Dieu j'ai les yeux qui saignent y'a de l'injection partout (bon, au moins, y'a du prepared statement). Tu ne dois pas htmlspecialchar avant de chercher ton pseudo dans la BDD, car je pense que ton pseudo (disons "a&b") est alors altéré (en "a&b", qui n'existe pas en BDD)
Voici une proposition de correction, c'est Paques, j'ai donc probablement zappé des trucs (et je tappe comme une vache ce soir donc bon)
mon Dieu j'ai les yeux qui saignent y'a de l'injection partout (bon, au moins, y'a du prepared statement). Tu ne dois pas htmlspecialchar avant de chercher ton pseudo dans la BDD, car je pense que ton pseudo (disons "a&b") est alors altéré (en "a&b", qui n'existe pas en BDD)
Voici une proposition de correction, c'est Paques, j'ai donc probablement zappé des trucs (et je tappe comme une vache ce soir donc bon)
<?php
// Centraliser les credentials (si possible ne pas les mettre directement dans la source PHP dans les centraliser dans un autre fichier PHP)
function pdoFactory(): PDO {
return new PDO('mysql:host=127.0.0.1;dbname=test', 'root', '',array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION ));
}
// Evite d'ouvrir la session tant qu'elle ne sert à rien
// session_start();
// en cas d'erreur, on ne donne pas d'info au client (joueur)
function failed(): void {
header('Content-Type: text/plain');
http_response_code(500);
echo "Un truc s'est mal passé, contactez l'admin du jeu";
}
// Echappement des textes avant insertion dans une string HTML (cf "XSS")
function html(string $str): string {
return htmlentities($str, ENT_QUOTES, 'UTF-8');
}
try
{
// Cette méthode de la callback évite de laisser filtrer les credentials (en les laissant dans des consts ou des variables)
$pdo = pdoFactory();
// En effet, pas besoin de préparer une query statique, en revanche, quel est son but?
$stmt = $pdo->query('SELECT pseudo,mdp FROM test');
$messages = $stmt->fetchAll(PDO::FETCH_OBJ);
// Laisse l'entièreté du code dans ton "try", de sorte qu'une erreur (exception) dans le code soit également catchée et traitée
foreach ($messages as $message) {
echo '<p>Le pseudo : ' . html($message->pseudo) . '</p>';
// Alors, heu, normalement on n'affiche pas les mots de passe hein... Mais je suppose que c'est pour debug
echo '<p>Le mdp :' . html($message->mdp) . '</p>';
}
// C'est une mauvaise pratique de traiter le formulaire dans la même page que là où il est construit
// Mieux vaut traiter le formulaire dans une page dédiée, qui ne fait que ça (et qui, souvent, redirige à la fin soit vers une page d'erreur soit vers la page du jeu après connection)
if (isset($_POST['formconnexion'])) {
// Je pense que ton soucis venait du "htmlspecialchars" mal placé ici (il n'a pas à être là)
// Utilise les fonctions de filtre des données d'entrée, car rien ne dit que "$_POST['formconnexion']" ne sera pas un array!
$pseudoconnect = filter_input(INPUT_POST, $_POST['pseudoconnect'], FILTER_VALIDATE_REGEXP, array(/* je ne sais plus, je te laisse chercher dans la doc*/);
// Non, ne réinvente pas les hashages de mots de passe (mais c'est bien de savoir qu'on ne les stocke pas en clair, c'est déjà ça)
// $mdpconnect = sha1($_POST['mdpconnect'], PASSWORD_DEFAULT);
if (is_string($pseudoconnect) && $pseudoconnect && is_string($mdpconnect) && $mdpconnect) {
// Ne sélectionne que ce qui est utile, pas tout
$requser = $pdo-> prepare('SELECT mdp FROM test WHERE pseudo = ?');
$requser->execute(array($pseudoconnect, $mdpconnect));
// Tu ne peux pas vérifier les mdp comme ça, la BDD ne peut pas faire ce travail (dans le cadre présent)
$userinfos = $requser->fetchAll(PDO::FETCH_OBJ);
if ($userinfos && password_verify($mdpconnect, $userinfos[0]->mdp)) {
// Ca n'a pas de sens de nommer ça "erreur"
$msg = "Connecté.";
} else {
$msg = "Mauvais pseudo ou mot de passe.";
}
} else {
$msg = "Tous les champs doivent être complétés !";
}
}
} catch (Throwable $e) { // Throwable est une interface encapsulant "encore plus d'erreur", cf doc
// Non, l'utilisateur ne doit pas savoir si un truc a foiré dans le code: cela ne doit apparait que dans tes logs
//exit('<b>Catched exception at line '. $e->getLine() .' :</b> '. $e->getMessage());
// Y'a mieux comme façon de logger, mais on s'en contentera
error_log(print_r($e, true));
pageFailed();
return;
}
// Le doctype ainsi que le header Content-Type doivent figurer, pour indiquer au navigateur ce qu'on lui envoie
header('Content-Type: text/html;charset=utf-8');
?><!DOCTYPE html>
<html>
<head>
<!-- A mettre au plus tôt dans le code, mais normalement, c'est le header HTTP "Content-Type: text/html;charset=utf-8" qui devrait définir ca -->
<meta charset="utf-8"/>
<title>TUTO PHP - Connexion</title>
<!-- Ca devrait être dans un fichier CSS dédié, chargé via <link rel="stylesheet" type="text/css" href="xxx.css"/> -->
<style>
div {
text-align: center;
}
</style>
</head>
<body>
<?php
// Point de vue UX (user experience), IMO, les messages d'erreur/succès devraient aller avant les formulaires, et non après
// car ainsi, on conditnue la lecture de la page pour corriger les erreurs plutôt que de devoir revenir en arrière dans la page si l'erreur est après le formulaire
if (isset($msg)) {
echo '<font color="red">' . html($msg) . '</font>' ;
}
?>
<!-- Evite les attributs de présentation HTML: mets ça dans un fichier CSS, chargé dans le "head" -->
<div>
<h2>Connexion :</h2>
<!-- Idem, les "br" ne doivent pas servir à rajouter des espaces visuels: utilise margin (ou padding) via le CSS pour ça -->
<!-- Comme dit, le traitement du formulaire devrait se faire dans une autre page, sinon, ce sera vite un bordel innommable -->
<form method="POST" action="autrepage.php">
<!-- Pense à toujours mettre un title ou un label aux champs de formulaire: ça aide les lecteurs d'écran, les plugins de navigateurs et les moteurs de recherche -->
<label>
Pseudo: <input type="text" name="pseudoconnect" placeholder="Pseudo" title="Pseudo"/>
</label>
<label>
Password: <input type="password" name="mdpconnect" placeholder="Votre mot de passe" title="Mot de passe"/>
</label>
<-- Button ou input, c'est un peu pareil, mais un input submit avec un name va générer un champ de formulaire supplémentaire, donc des données inutiles envoyées au serveur -->
<button type="submit">Gérez votre empire</button>
</form>
</div>
</body>
</html>