Bonjour a tous et a toutes, j'ai écris un code afin que les futurs inscrits a mon site puissent réinitialiser leurs mots de passe si jamais ils l'ont oublié.j'ai fait le necessaire afin qu'ils puissent reçevoir un lien token dans leur boite mail afin de pouvoir entrer leur nouveau mot de passe, sauf que une fois le nouveau mot de passe entré ils n'accèdent pas a leur espace perso comme je l'avais programé.Et je vois pas l'erreur, ci dessous mon code , merci encore d'avance.

<?php
SESSION_START ();
print_r($_SESSION);
if(isset($_GET['adresse_mail'])&& isset($_GET['token'])){
require 'connexion_base_de_donnees.php';

$date=date('y/m/d H:i:s');

$req= $pdo->prepare ('SELECT * FROM infosdesclients WHERE adresse_mail=? AND forgot_mdp=? AND date_token> DATE_SUB(date_token, INTERVAL 30 MINUTE)');

$req->execute([$_GET['adresse_mail'],$_GET['token']]);
$tab= $req->FETCHALL();
    if(count($tab)==0) {

        header('location: index.php'); die ();}     

} 

else{
    if($tab){
    if(!empty($_POST)){
        if(!empty($_POST['nouveau_mot_de_passe'])&& $_POST['nouveau_mot_de_passe']==$_POST['confirmation_nouveau_mot_de_passe']){

            $_POST['nouveau_mot_de_passe']=$nouveau_mot_de_passe;

         $pdo->prepare('UPDATE infosdesclients SET mot_de_passe = ?');
        $pdo->execute([$nouveau_mot_de_passe]);

        $_SESSION['authentification']=$tab;

        header('location: page_de_jeu.php');

        }

    }

}}

?>

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="page_principal_de_jeu.css">
<title>Konamicash</title>
</head>

<body>

<form action="" method="POST">
<div class="form-group">
<label for ="">Nouveau mot de passe</label>
<input type="password" name="nouveau_mot_de_passe" class=""/>
</div>

<div class="form-group">
<label for ="">confirmation_nouveau_mot_de_passe</label>
<input type="password" name="confirmation_nouveau_mot_de_passe" class=""/>
</div>
<button type="submit" name="valider">valider </button>
</form>

</body>
</html>

Ce que je veux

pouvoir accéder a mon espace personnel après avoir réinitialisé mon mot de passe

Ce que j'obtiens

il ne se passe rien je suis redirigé sur la page de réinitialisation du mot de passe

8 réponses


<?php
SESSION_START();
print_r($_SESSION);
$count_tab = 0;
if (isset($_GET['adresse_mail']) && isset($_GET['token'])) {
require 'connexion_base_de_donnees.php';

$date = date('y/m/d H:i:s');

$req = $pdo->prepare('SELECT * FROM infosdesclients WHERE adresse_mail=? AND forgot_mdp=? AND date_token> DATE_SUB(date_token, INTERVAL 30 MINUTE)');

$req->execute([$_GET['adresse_mail'], $_GET['token']]);
$tab = $req->FETCHALL();
$count_tab = count($tab);

} else {
header('location: index.php');
die();
}

if (isset($_POST['valider']) and $count_tab > 0) {
if (!empty($_POST['nouveau_mot_de_passe']) && $_POST['nouveau_mot_de_passe'] == $_POST['confirmation_nouveau_mot_de_passe']) {

    $nouveau_mot_de_passe = $_POST['nouveau_mot_de_passe'];

    $pdo->prepare('UPDATE infosdesclients SET mot_de_passe = ?');
    $pdo->execute([$nouveau_mot_de_passe]);

    $_SESSION['authentification'] = $tab;

    header('location: page_de_jeu.php');
}

}

?>

<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
<link rel="stylesheet" href="page_principal_de_jeu.css">
<title>Konamicash</title>
</head>

<body>

<form action="" method="POST">
    <div class="form-group">
        <label for="">Nouveau mot de passe</label>
        <input type="password" name="nouveau_mot_de_passe" class="" />
    </div>

    <div class="form-group">
        <label for="">confirmation_nouveau_mot_de_passe</label>
        <input type="password" name="confirmation_nouveau_mot_de_passe" class="" />
    </div>
    <button type="submit" name="valider">valider </button>
</form>

</body>

</html>

Meeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeerciiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii pekeni, ta rectification du code fonctionne parfaitement bien, du coup si possible tu peux m'expliquer ce qui clochait stp?

Hello,

Il serait pas mal de faire attention à l'indentation car cela rends plus dur pour aider à la compréhension du problème.

Dans ton code ta condition sur date_token sera toujours vrai, car date_token > date_token - 30 est toujours vrai :)

A l'attention de @Pekenio : C'est bien de vouloir aider une personne, mais essaye aussi de donner plus d'explication et surtout quand un code est mal présenter (indentation, nom utilisé, etc.) essaye de changer pour montrer à l'auteur une meilleure manière de faire. Exemple le mot de passe qu'il enregistre est en claire. Il ne faut pas faire ça.

Voici un code mieux écrit : (attention j'ai hash le mot de passe)

<?php

// Même si on peut, mettez le nom des fonctions avec la bonne casse
// Dans le code il y a des mélanges anglais, français (forgot_mdp par exemple).
// Il faut choisir une langue et s'y tenir, donc forgot_mdp devrait être mot_de_passe_oublie ou forgot_password

session_start();

$email = $_GET['adresse_mail'] ?? null;
$token = $_GET['token'] ?? null;

if (empty($email) || empty($token)) {
    header('HTTP/1.0 302 Found', true, 302);
    header('Location: index.php');
    exit();
}

// La condition NOW() > DATE_ADD(date_token, INTERVAL 30 MINUTE) dépend de si
// la date enregistré est la date de la demande ou la date d'expiration
// Si c'est la date d'expiration il faut mettre : date_token < NOW()
$reqUser = $pdo->prepare('SELECT count(*) as nb FROM infosdesclients
    WHERE adresse_mail = :email AND forgot_mdp = :token
    AND DATE_ADD(date_token, INTERVAL 30 MINUTE) < NOW()');
$reqUser->execute([
    'email' => $email,
    'token' => $token,
]);

$nbUser = (int) $reqUser->fetch(PDO::FETCH_ASSOC)['nb'];
if ($nbUser === 0) {
    header('HTTP/1.0 302 Found', true, 302);
    header('Location: index.php');
    exit();
}

if (!empty($_POST)) {
    $errors = [];
    $newPassword = $_POST['nouveau_mot_de_passe'] ?? null;
    $confirmNewPassword = $_POST['confirmation_nouveau_mot_de_passe'] ?? null;

    if (empty($newPassword) || empty($confirmNewPassword)) {
        $errors['empty'] = 'Merci de remplir tous les champs obligatoires';
    }

    if (mb_strlen($newPassword) < 8) {
        $errors['password'] = 'Votre mot de passe est trop court (8 caractères minimum)';
    }

    if ($newPassword !== $confirmNewPassword) {
        $errors['confirm'] = 'Les mots de passe ne correspondent pas';
    }

    if (empty($errors)) {
        // Privilégiez les paramètres nommés (les :nom) plutôt que les paramètres positionnés (les ?)
        $reqUpdatePassword = $pdo->prepare('UPDATE infosdesclients
            SET mot_de_passe = :password, forgot_mdp = NULL, date_token = NULL
            WHERE adresse_mail = :email AND forgot_mdp = :token');
        $reqUpdatePassword->execute([
            'email'=> $email,
            'token'=> $token,
            'password' => password_hash($newPassword, PASSWORD_DEFAULT, ['cost' => 14]),
        ]);

        // Ne pas reconnecter l'utilisateur, il doit se connecter avec son nouveau mot de passe
        header('HTTP/1.0 302 Found', true, 302);
        header('Location: index.php');
        exit();
    }
}

?>
<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="utf-8">
    <link rel="stylesheet" href="page_principal_de_jeu.css">
    <title>Konamicash</title>
</head>
<body>
    <!-- Gestion des erreurs -->
    <?php if (!empty($errors)): ?>
        <div class="alert alert-danger">
            <p>Vous n'avez pas rempli le formulaire correctement</p>
            <ul>
                <?php foreach ($errors as $error): ?>
                    <li><?= $error ?></li>
                <?php endforeach ?>
            </ul>
        </div>
    <?php endif ?>
    <form action="" method="POST">
        <div class="form-group">
            <!-- le for doit pointer sur l'id de l'input, pensons aux personnes malvoillantes :) -->
            <label for="nouveau_mot_de_passe">Nouveau mot de passe</label>
            <input type="password" name="nouveau_mot_de_passe" class="" id="nouveau_mot_de_passe" />
        </div>
        <div class="form-group">
            <label for="confirmation_nouveau_mot_de_passe">confirmation_nouveau_mot_de_passe</label>
            <input type="password" name="confirmation_nouveau_mot_de_passe" class="" id="confirmation_nouveau_mot_de_passe" />
        </div>
        <!-- En terme UX c'est mieux d'indiquer l'action que l'on effectue plutôt que juste "valider" -->
        <button type="submit">Changer mon mot de passe</button>
    </form>

</body>
</html>

merco beaucoup pour tes éclaircicement et ton code aussi quenti77, et tu as parfaitement raison , c'est toujours mieux de comprendre ses erreurs pour ne pas commettre les memes plus tard, merci encore

quenti77 merci encore pour ton aide, j'ai relu ton code et dans un de tes commentaires tu as dis qu'il fallait mieux privilégier les paramètres nommés (les :nom) plutôt que les paramètres positionnés (les ?), peux-tu m'en dire plus? je sais pas la différences(je me suis lancer dans le codage il n'y a pas deux mois, merci d'avance d'éclaicir la lanterne de la pauvre demoiselle en detresse que je suis :-))

peux-tu m'en dire plus?

En effet en gros les 2 permettent la même chose mais la différence c'est qu'avec la version nommé :qqchose tu visualise mieux dans la requête à quoi ça correspond. Sur une requête simple comme un select avec un where ça passe mais si je te donne une requête d'insertetion avec 10 champs à remplir, les ? ne seront pas lisibles et il faudra pas se tromper dans l'ordre des éléments que tu passe au execute. Voici un exemple mais bien sur il faudra donner un nom plus claire dans ton code que "valX" ^^

<?php
$reqInsertWithPositional = $pdo->prepare('INSERT INTO ma_table(col1, col2, col3, col4, col5, col6)
    VALUES (?, ?, ?, ?, ?, ?)');
$reqInsertWithPositional->execute([$val1, $val2, $val3, $val4, $val5, $val6]);

$reqInsertWithNomminative = $pdo->prepare('INSERT INTO ma_table(col1, col2, col3, col4, col5, col6)
    VALUES (:val1, :val2, :val3, :val4, :val5, :val6)');
$reqInsertWithNomminative->execute([
    ':val1' => $val1,
    ':val2' => $val2,
    ':val3' => $val3,
    ':val4' => $val4,
    ':val5' => $val5,
    ':val6' => $val6,
]);

Enfin si au lieu de passer par execute tu dois passer par bindValue alors tu aura :

$reqInsertWithPositional->bindValue(0, $val1, PDO::PARAM_STR);
$reqInsertWithPositional->bindValue(1, $val2, PDO::PARAM_STR);
$reqInsertWithPositional->bindValue(2, $val3, PDO::PARAM_STR);
$reqInsertWithPositional->bindValue(3, $val4, PDO::PARAM_STR);
$reqInsertWithPositional->bindValue(4, $val5, PDO::PARAM_STR);
$reqInsertWithPositional->bindValue(5, $val1, PDO::PARAM_STR);

$reqInsertWithPositional->bindValue(':val1', $val2, PDO::PARAM_STR);
$reqInsertWithPositional->bindValue(':val2', $val3, PDO::PARAM_STR);
$reqInsertWithPositional->bindValue(':val3', $val4, PDO::PARAM_STR);
$reqInsertWithPositional->bindValue(':val4', $val5, PDO::PARAM_STR);
$reqInsertWithPositional->bindValue(':val5', $val1, PDO::PARAM_STR);
$reqInsertWithPositional->bindValue(':val6', $val1, PDO::PARAM_STR);

Donc après je te laisse juger par toi-même mais perso je trouve ça beaucoup plus lisible avec la version nommé :)

tu as entièrement raison c'est beaucoup plus pratique

au fait j'aimerais avoir des informations sur ce qu'est le cron job, donc j'ai posté a l'instant un nouveau sujet dans le forum, si tu as des informations peux tu me répondre là bas stp? thank you