Formulaire connexion mot de passe haché sha1

 /**
     * Permet d'identifier un utilisateur
     **/
    function login($d){
        global $PDO;
        $req = $PDO->prepare('SELECT users.id, users.login, users.password, users.mail, users.address, users.avatar,roles.name,roles.slug,roles.level  FROM users LEFT JOIN roles ON users.role_id=roles.id WHERE login=:login AND password = :password');
        $req->execute($d); 
        $data = $req->fetchAll();
        if(count($data)>0){
                $_SESSION['Auth'] = $data[0]; 
                return true;
        }
        return false; 
    }
if(!empty($_POST)){
    if($Auth->login($_POST)){

    }else{
        echo 'Mauvais identifiants'; 
    }
}

Ce que je veux

j'ai fait une page d'inscription ou le mot de passe est cripter dans la bdd et j'aimerais avec les ongles de connexion si dessus pourvoir me connecter avec un mot de passe cripter (Faire en sorte qu'il le decripte pour pourvoir se connecter )

7 réponses


Hello,

Alors déjà les mots de passe en base ne sont pas "crypter" mais hasher et d'ailleurs même si c'était "crypter" ça serait chiffrer.

Ensuite je ne sais pas quel tuto tu as pu voir mais on utilise plus SHA1 depuis plus de 5, 10 ans donc je te conseil d'oublier le tuto que tu as vu.

Donc pour l'inscription en suivant ce que tu as fait ça donnerait :

<?php

// Dans ton autre fichier php
$db = new PDO('mysql:host=localhost;dbname=test', 'root', 'root');
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);

// Dans ton fichier php pour le register
function register(PDO $db, array $userData): void
{
    $query = $db->prepare('INSERT INTO users (...tes_champs, password) VALUES (...tes_valeurs, :password)');
    $query->execute($userData);

    // Reste du code
}

$email = $_POST['email'] ?? null;
$password = $_POST['password'] ?? null;
// Je ne fais pas les autres champs pour simplifier

$userData = [
    'email' => $email,
    'password' => password_hash($password, PASSWORD_DEFAULT, ['cost' => 14]),
];

register($db, $userData);

Plusieurs chose

  • On est en php 8.1 / 8.2, tu peux typer les paramètres et retour de tes fonctions.
  • J'utilise password_hash qui est la fonction php à utiliser pour hasher ces mots de passe
  • Je passe la connexion en paramètre, il faut banir l'utilisation de "global"

Maintenant que ton mot de passe est mieux gérer on peut passer à la connexion.

function login(PDO $db, string $username, string $password) {
    $query = $db->prepare('SELECT ...les_champs_que_tu veux  FROM users WHERE login = :username');
    $query->execute(['username' => $username]);

    $user = $query->fetch();
    if ($user === false) {
        return false;
    }

    if (!password_verify($password, $user['password'])) {
        return false;
    }

    $_SESSION['auth'] = $user;
    return true;
}

if (!login($db, $_POST['username'] ?? '', $_POST['password'] ?? '')) {
    // echo 'Identifiants incorrects';
    exit();
}

// echo 'Vous êtes connecté';

Voici les points à revoir par rapport à ton code :

  • Pas d'utilisation de rowCount sur une requête SELECT car cette dernière pourrait te renvoyer 0 même si tu as des données
  • Utilisation de fetch et non fetchAll qui permet de savoir directement si j'ai un user on nom
  • Comme je suis dans une fonction j'utilise la technique du else-less. Cela veut dire que je return le plus tôt possible quand j'ai une condition
  • Je ne passe pas tout un tableau alors que 2 valeurs (plus la co à la db) suffisent

En tout cas voilà déjà pour commencer. Comme dis plus haut, je te conseil de changer de tuto / formations ou de bien regarder si la personne à bien fait comme tu le fais.

slt
Donc mon login / inscription n'est pas bon : est ce que tu pourrais revoir mon code stp :

<?php
$bdd = new PDO('mysql:host=localhost;dbname=test', 'root', 'root');

if(isset($_POST['forminscription'])) {
   $login = htmlspecialchars($_POST['login']);
   $mail = htmlspecialchars($_POST['mail']);
   $mail2 = htmlspecialchars($_POST['mail2']);
   $mdp = sha1($_POST['mdp']);
   $mdp2 = sha1($_POST['mdp2']);
   if(!empty($_POST['login']) AND !empty($_POST['mail']) AND !empty($_POST['mail2']) AND !empty($_POST['mdp']) AND !empty($_POST['mdp2'])) {
      $pseudolength = strlen($login);
      if($pseudolength <= 255) {
         if($mail == $mail2) {
            if(filter_var($mail, FILTER_VALIDATE_EMAIL)) {
               $reqmail = $bdd->prepare("SELECT * FROM users WHERE mail = ?");
               $reqmail->execute(array($mail));
               $mailexist = $reqmail->rowCount();
               if($mailexist == 0) {
                  if($mdp == $mdp2) {
                     $insertmbr = $bdd->prepare("INSERT INTO users(login, mail, password, role_id, avatar) VALUES(?, ?, ?, ?, ?)");
                     $insertmbr->execute(array($login, $mail, $mdp , "3", "default.png"));
                     header("Location: login.php");
                  } else {
                     $erreur = "Vos mots de passes ne correspondent pas !";
                  }
               } else {
                  $erreur = "Adresse mail déjà utilisée !";
               }
            } else {
               $erreur = "Votre adresse mail n'est pas valide !";
            }
         } else {
            $erreur = "Vos adresses mail ne correspondent pas !";
         }
      } else {
         $erreur = "Votre pseudo ne doit pas dépasser 255 caractères !";
      }
   } else {
      $erreur = "Tous les champs doivent être complétés !";
   }
}

if(!empty($_POST)){
    if($Auth->login($_POST)){

    }else{
        echo 'Mauvais identifiants'; 
    }
}
?>

<html lang="fr">
   <head>
      <title>FamilysMods - Connexion</title>
      <meta charset="UTF-8">
       <meta http-equiv="X-UA-Compatible" content="IE=edge">
       <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <link rel="icon" href="img/Logo.png" type="image/png">
      <link rel="stylesheet" href="css/connexion.css">
      <script src="https://kit.fontawesome.com/7895ff7bdb.js" crossorigin="anonymous"></script>
   </head>
   <body>
      <div class="container" id="container">
         <div class="form-container sign-up-container">
            <form method="POST" action="">
               <h1>Créer un compte</h1>
               <div class="social-container">
                  <a href="#" class="social"><i class="fab fa-google-plus-g"></i></a>
                  <a href="#" class="social"><i class="fab fa-discord"></i></a>
               </div>
               <span>ou utilisez votre email pour vous inscrire</span>
               <input type="text" placeholder="Votre pseudo" id="login" name="login" value="<?php if(isset($login)) { echo $login; } ?>" />
               <input type="email" placeholder="Votre mail" id="mail" name="mail" value="<?php if(isset($mail)) { echo $mail; } ?>" />
               <input type="email" placeholder="Confirmez votre mail" id="mail2" name="mail2" value="<?php if(isset($mail2)) { echo $mail2; } ?>" />
               <input type="password" placeholder="Votre mot de passe" id="mdp" name="mdp" />
               <input type="password" placeholder="Confirmez votre mdp" id="mdp2" name="mdp2" />
               <button type="submit" name="forminscription">S'inscrire</button>
            </form>
            <br>
            <?php
            if(isset($erreur)) {
               echo '<font color="red">'.$erreur."</font>";
            }
            ?>
            <br>
         </div>
         <div class="form-container sign-in-container">
            <form method="post" action="index.php?p=compte">
               <h1>S'identifier</h1>
               <div class="social-container">
                  <a href="#" class="social"><i class="fab fa-google-plus-g"></i></a>
                  <a href="#" class="social"><i class="fab fa-discord"></i></a>
               </div>
               <span>ou utilisez votre compte</span>
               <input type="text" name="login" placeholder="Mail" />
               <input type="password" name="password" placeholder="Mot de passe" />
               <a href="recuperation.php">Mot de passe oublié?</a>
               <button type="submit">Se connecter</button>
            </form>
            <br>
            <?php
            if(isset($erreur)) {
               echo '<font color="red">'.$erreur."</font>";
            }
            ?>
            <br>
         </div>
         <div class="overlay-container">
            <div class="overlay">
               <div class="overlay-panel overlay-left">
                  <h1>Content de te revoir !</h1>
                  <p>Pour rester en contact avec nous, veuillez vous connecter avec vos informations personnelles</p>
                  <button class="ghost" id="signIn">S'identifier</button>
                  <a href="https://www.famillysmods.fr"><button class="ghost">Accueil</button></a>
               </div>
               <div class="overlay-panel overlay-right">
                  <h1>Salut l'ami !</h1>
                  <p>Entrez vos données personnelles et commencez votre voyage avec nous</p>
                  <button class="ghost" id="signUp">S'inscrire</button>
                  <a href="https://www.famillysmods.fr"><button class="ghost">Accueil</button></a>
               </div>
            </div>
         </div>
      </div>
      <script src='js/connexion.js'></script>
   </body>
</html>

Je te remercie

Ah oui c'est vraiment un vieux tuto (ou un mauvais tuto :D ) (D'ailleurs si jamais tu es sur le discord de Grafikart tu peux me l'envoyer en mp ?)

Je vais essayé dans dire le plus ici, je vais essayé d'être assez clair :)

Commençons par la connexion à la bdd. Si cette connexion est vraiment dans le même fichier je te conseil de sortir le code dans un autre fichier.

<?php

// fichier connection.php

// N'oublie pas de remplacer les valeurs par les tiennes
const DB_HOST = 'localhost';
const DB_NAME = 'test';
const DB_USER = 'root';
const DB_PASS = 'root';

// Essaye de choisir entre mettre des noms en français ou en anglais, mais pas les deux en même temps
$dsn = 'mysql:host=' . DB_HOST . ';dbname=' . DB_NAME . ';charset=utf8';
$db = new PDO($dsn, DB_USER, DB_PASS);
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);

Le fait de séparer dans un autre fichier permet d'avoir la possibilité de l'inclure à plusieurs endroits mais de au besoin le modifier qu'a un seul endroit. C'est un peu comme créer une fonction. Cela permet la réutilisabilité.

Voici maintenant la page d'inscription :

<?php

// Je conseille de séparer le traitement de la vue (le HTML) dans des fichiers différents (ou url différentes)
// C'est plus propre et plus facile à maintenir

// Mais pour l'exemple, je vais tout mettre dans le même fichier.
// Je te laisserai le soin de séparer le traitement de la vue

// Je m'assure que je pars bien du bon dossier
require __DIR__ . '/connection.php';

// Sauf si tu as plusieurs formulaires sur la même page qui pointe ici,
// tu n'as pas besoin de conditionner sur le bouton
if (!empty($_POST)) {
    // Traitement du formulaire
    // Jamais de "htmlspecialchars" dans le traitement, c'est la vue qui s'en charge
    // Explication ici : https://zestedesavoir.com/articles/2489/ne-pas-confondre-faille-par-injection-sql-et-faille-xss/
    $login = $_POST['login'] ?? null;
    $email = $_POST['email'] ?? null;
    $password = $_POST['password'] ?? null;

    // On va retenir les erreurs dans un tableau
    // Cela va permettre d'éviter les "if" imbriqués
    $errors = [];

    if (empty($login) || empty($email) || empty($password)) {
        $errors[] = 'Tous les champs doivent être complétés !';
    }

    // tu peux utiliser strlen si l'extension mbstring n'est pas activée
    if (mb_strlen($login) > 255) {
        $errors[] = 'Votre pseudo ne doit pas dépasser 255 caractères !';
    }

    if (filter_var($email, FILTER_VALIDATE_EMAIL) === false) {
        $errors[] = "Votre adresse mail n'est pas valide !";
    }

    if (mb_strlen($password) < 12) {
        $errors[] = 'Votre mot de passe doit faire au moins 12 caractères !';
    }

    // Comme tu peux le voir ici, je n'utilise pas de double champs pour le mot de passe et pour l'email
    // C'est prouvé que cela ne sert pas, car souvent les personnes copient/collent les valeurs

    $reqUser = $db->prepare('SELECT id FROM users WHERE email = :email');
    $reqUser->execute(['email' => $email]);
    $user = $reqUser->fetch();
    if ($user) {
        $errors[] = 'Adresse mail déjà utilisée !';
    }

    if (empty($errors)) {
        // Si la valeur par défaut est connue (ici le "3" et le "default.png"), alors tu peux directement l'insérer dans la requête
        $insertUser = $db->prepare('INSERT INTO users (login, email, password, role_id, avatar) VALUES (:login, :email, :password, "3", "default.png")');
        $insertUser->execute([
            'login' => $login,
            'email' => $email,
            'password' => password_hash($password, PASSWORD_DEFAULT),
        ]);
        // Comme tu peux le voir c'est plus clair d'utiliser des paramètres nommés (avec les ":")
        // que d'utiliser des paramètres positionnels (avec "?")
        // Cela permet de ne pas se tromper dans l'ordre des paramètres
        // Et de pouvoir réutiliser le même paramètre plusieurs fois dans la requête

        // Si tu veux rediriger vers une autre page, tu peux utiliser la fonction "header"
        // j'y ajoute les paramètres replace et response_code pour être sûr que la requête renvoie bien un code 302
        header('Location: login.php', true, 302);

        // On arrête le script, car sinon le script continue et affiche le formulaire
        // Pour ici ce n'est pas très grave, mais si tu as du code après le header, il sera exécuté
        // et par exemple un admin panel pourrait afficher des informations sensibles à un utilisateur non connecté
        exit();
    }
}

?>
<!DOCTYPE html>
<html lang="fr">
<head>
    <title>TITLE</title>
    <!-- je ne mets pas tout le code HTML -->
</head>
<body>
<?php if (!empty($errors)): ?>
    <p>Erreurs lors de la soumission du formulaire</p>
    <ul>
        <?php foreach ($errors as $error): ?>
            <li><?= htmlspecialchars($error) ?></li>
        <?php endforeach; ?>
    </ul>
<?php endif; ?>
<form method="post">
    <div>
        <label for="login">Pseudo</label>
        <input type="text" name="login" id="login" value="<?= htmlspecialchars($login ?? '') ?>">
        <!-- Vraiment pratique cet opérateur "??" apparût avec php 7.0 il y a 6, 7 ans environ :D -->
    </div>
    <div>
        <label for="email">Email</label>
        <input type="email" name="email" id="email" value="<?= htmlspecialchars($email ?? '') ?>">
    </div>
    <div>
        <label for="password">Mot de passe</label>
        <input type="password" name="password" id="password">
    </div>
    <button type="submit">S'inscrire</button>
</form>
</body>
</html>

J'ai mis des commentaires dans le code mais si tu as des questions je peux y répondre.

Je n'ai fais que l'inscription, je te laisse voir pour la connexion.

Bonjour, je viens de voir ceci dans ce message:
<code>$login = $_POST['login'] ?? null;</code>
Ceci m'intrigue: "?? null"

Il s'agit du Null Coalescing Operator. En gros cela permet d'eviter de faire un ternaire pour vérifier si une valeur existe et est non null.

Exemple :

// Avant
$email = isset($_POST['email']) ? $_POST['email'] : null;

// Maintenant
$email = $_POST['email'] ?? null;

On peut même aller plus loin et enchaîner les vérifications

// Avant
$defaultName = '';
if (isset($user)) {
        $defaultName = $user->name;
} else if (isset($admin)) {
        $defaultName = $admin->realName;
}

// Maintenant
$defaultName = $user->name ?? $admin->realName ?? '';

Tu peux chercher des exemples sur internet avec le nom de l'operateur.

Ça va être pratique et facile à utiliser. Merci quenti77.

Et je vois que pour placer un code, <code>...</code>
ne fonctionne pas afin de montrer un bout de code.

Oui l'éditeur est un éditeur markdown. Donc pour mettre du code il faut l'entourer de ` (back-ticks, alt gr + 7 sur un clavier pc azerty)

Exemple :
```
ton code
```

ton code

Mais tu peux aussi mettre en gras ou italique en entourant de 1 ou 2 *. Je te laisse regarder sur internet la syntaxe markdown :)