JeuWeb - Crée ton jeu par navigateur
Script connexion basique - Version imprimable

+- JeuWeb - Crée ton jeu par navigateur (https://jeuweb.org)
+-- Forum : Discussions, Aide, Ressources... (https://jeuweb.org/forumdisplay.php?fid=38)
+--- Forum : Programmation, infrastructure (https://jeuweb.org/forumdisplay.php?fid=51)
+--- Sujet : Script connexion basique (/showthread.php?tid=7983)

Pages : 1 2


Script connexion basique - Tortuel - 22-04-2019




RE: Script connexion basique - Xenos - 22-04-2019

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)

<?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>



RE: Script connexion basique - Tortuel - 22-04-2019

Merci beaucoup pour ta réponse, j'ai copié ton code et y a une erreur ligne 3 Big Grin
Parse error: syntax error, unexpected ':', expecting '{' in
Ta réponse est vraiment au top !


RE: Script connexion basique - Xenos - 22-04-2019

T'es probablement pas en PHP 7, je te conseille de te mettre à jour (7.3 doit être la dernière version sortie)


RE: Script connexion basique - Tortuel - 22-04-2019

Je suis effectivement avec Wamp Server php 5.58 à priori :/


RE: Script connexion basique - Xenos - 22-04-2019

Tu peux donc soit le mettre à jour (installer une nouvelle version de PHP sur ton wamp), soit virer les typages de retour des fonctions (les :void et Confusedtring). Mais je crois que les typages des paramètres sont alors aussi à virer, et la fonction password_verify n'est peut être pas existante en 5.5 (d'où la 1ere et meilleure piste: installer un PHP 7.3)


RE: Script connexion basique - Tortuel - 23-04-2019

Salut,
Voila c'est mis à jour Smile
Mon script était un script de test pour apprendre et comprendre, d'ou les trucs complètement cons comme affichés les pseudos, mdps, etc...

Y a des choses que je ne comprends pas dans ton code (normal je suis au tout début ><).

Pourquoi aucun message ne s'affiche ?

Tu me conseilles donc, d'envoyer le joueur soit sur sa page de jeu si tout est ok soit dans une page pour le rediriger et retaper ses pass ?


RE: Script connexion basique - Xenos - 23-04-2019

Aucun message ne s'affiche car il n'y a plus de "formconnection" dans les champs envoyés par le client (puisque le input submit n'est plus là; ça illustre le fait que précédemment, le navigateur envoyait cette donnée inutilement). En revanche, j'ai oublié de changer le "isset" en conséquences (pour un isset de pseudoconnect par exemple).

Oui, je te conseille de bien séparer l'affichage et le traitement du formulaire:
- 1 page affiche le formulaire (et ne fait donc pas d'accès DB)
- 1 page traite le formulaire (et fait l'accès DB); si l'accès est OK, cette page redirige vers la suite du jeu, et si l'accès n'est pas OK, cette page redirige soit vers la 1ere (en passant en paramètre un identifiant de message d'erreur par exemple; attention à ne pas insérer des XSS!) soit vers une troisième page (indiquant un message d'erreur statique correspondant)


RE: Script connexion basique - Tortuel - 23-04-2019

(23-04-2019, 02:01 PM)Xenos a écrit : Aucun message ne s'affiche car il n'y a plus de "formconnection" dans les champs envoyés par le client (puisque le input submit n'est plus là; ça illustre le fait que précédemment, le navigateur envoyait cette donnée inutilement). En revanche, j'ai oublié de changer le "isset" en conséquences (pour un isset de pseudoconnect par exemple).

Oui, je te conseille de bien séparer l'affichage et le traitement du formulaire:
- 1 page affiche le formulaire (et ne fait donc pas d'accès DB)
- 1 page traite le formulaire (et fait l'accès DB); si l'accès est OK, cette page redirige vers la suite du jeu, et si l'accès n'est pas OK, cette page redirige soit vers la 1ere (en passant en paramètre un identifiant de message d'erreur par exemple; attention à ne pas insérer des XSS!) soit vers une troisième page (indiquant un message d'erreur statique correspondant)

J'ai réussi à avoir le message "Tous les champs doivent être complétés" par contre si la connexion fonctionne ou si le pseudo ou mdp est faux cela m'affiche :
J'ai mis un isset sur pseudoconnect et mdpconnect.
 Error: Call to undefined function pageFailed() in C:\wamp64\www\Tutos\connexion.php on line 70

Je vois que j'ai encore beaucoup de chemin à faire avant de coder le "jeu" ! Big Grin



RE: Script connexion basique - Xenos - 23-04-2019

Tu devrais être capable de corriger l'erreur seul dans un cas comme ça... Je te conseille d'en apprendre un peu plus sur PHP (et probablement sur SQL aussi) avant d'entamer un taff lourd comme un jeu. Dans le cas présent, j'ai juste mal nommé ma fonction "failed" et "pageFailed" (c'est l'inconvénient de faire de la correction de code dans un forum: on n'a pas les inspections d'un IDE : ) )