Bonjour tout le monde,

J'ai un problème avec la tuto pour une gestion d'un espace membre. Lorsque je me créé un compte et que je me connecte, tout va bien mais lorsque j'essaie de réinitialiser le password de ce compte dans la page forget.php, j'entre l'email, je saisi le lien que j'ai reçu dans maildev et je le copie dans ma barre d'adresse, on me dit le token n'est pas valide et on me redirige vers la page de connexion. Donc, je pense qu'il y a une erreur dans mon code (même si on ne me précise pas où) et je ne suis pas sûr où se trouve l'erreur. J'ai aussi un problème avec le checkbox "se souvenir de moi", lorsque je le clique, on n'enregistre pas le remember_token dans la base de donnés. Voilà mon code;

forget.php

<?php
if(!empty($_POST) && !empty($_POST['email'])){
    require_once 'inc/db.php';
    require_once 'inc/functions.php';
    $req = $pdo->prepare('SELECT * FROM users WHERE email = ? AND confirmed_at IS NOT NULL');
    $req->execute([$_POST['email']]);
    $user = $req->fetch();
    if($user){
        session_start();
        $reset_token = str_random(60);
        $pdo->prepare('UPDATE users SET reset_token = ?, reset_at = NOW() WHERE id = ?')->execute([$reset_token, $user->id]);
        $_SESSION['flash']['success'] = 'Les instructions du rappel de mot de passe vous ont été envoyées par email.';
        mail($_POST['email'], 'Réinitialisement de votre mot de passe.', "Afin de réinitialiser votre mot de passe merci de cliquer sur ce lien\n\nhttp://localhost/login/reset.php?id={$user->id}&token=$reset_token");
        header('Location: login.php');
        exit();
    }else{
        $_SESSION['flash']['danger'] = 'Aucun compte correspond à cette adresse.';
    }
}
?>
<?php require 'inc/functions.php';?>
<?php require 'inc/header.php'; ?>

<h1>Mot de passe oublié</h1>

<form action="" method="POST">

    <div class="form-group">
       <label for="">Email</label>
       <input type="email" name="email" class="form-control" />
    </div>

    <button type="submit" class="btn btn-primary">Se connecter</button>

</form>

<?php debug($_SESSION) ?>

<?php require 'inc/footer.php'; ?>

reset.php

<?php
if(isset($_GET['id']) && isset($_GET['token'])){
    require 'inc/db.php';
    require 'inc/functions.php';
    $req = $pdo->prepare('SELECT * FROM users WHERE id = ? AND reset_token IS NOT NULL AND reset_token = ? AND reset_at > DATE_SUB(NOW(), INTERVAL 30 MINUTE)');
    $req->execute([$_GET['id'], $_GET['token']]);
    $user = $req->fetch();
    if($user){
        if(!empty($_POST)){
            if(!empty($_POST['password']) && $_POST['password'] == $_POST['password_confirm']){
                $password = password_hash($_POST['password'], PASSWORD_BCRYPT);
                $pdo->prepare('UPDATE users SET password = ?, reset_at = NULL, reset_token = NULL')->execute([$password]);
                session_start();
                $_SESSION['flash']['success'] = 'Votre mot de passe a bien été modifié';
                $_SESSION['auth'] = $user;
                header('Location: account.php');
                exit();
            }else {
                $_SESSION['flash']['danger'] = "Les mots de passe ne correspondent pas";
            } 
        }
    }else{
        session_start();
        $_SESSION['flash']['danger'] = "Ce token n'est pas valide";
        header('Location: login.php');
        exit();
    }
}else{
    header('Location: login.php');
    exit();
}
?>
<?php require 'inc/header.php'; ?>

<h1>Rénitialiser mon mot de passe</h1>

<form action="" method="POST">

    <div class="form-group">
       <label for="">Mot de passe</label>
       <input type="password" name="password" class="form-control" />
    </div>

    <div class="form-group">
       <label for="">Confirmation de mot de passe</label>
       <input type="password" name="password_confirm" class="form-control" />
    </div>

    <button type="submit" class="btn btn-primary">Réinitialiser votre mot de passe</button>

</form>

<?php debug($_SESSION) ?>

<?php require 'inc/footer.php'; ?>

login.php

<?php
require_once 'inc/functions.php';
reconnect_from_cookie();
if(isset($_SESSION['auth'])){
    header('Location: account.php');
    exit();
}
if(!empty($_POST) && !empty($_POST['username']) && !empty($_POST['password'])){
    require_once 'inc/db.php';
    $req = $pdo->prepare('SELECT * FROM users WHERE (username = :username OR email = :username) AND confirmed_at IS NOT NULL');
    $req->execute(['username' => $_POST['username']]);
    $user = $req->fetch();
    if(password_verify($_POST['password'], $user->password)){
        $_SESSION['auth'] = $user;
        $_SESSION['flash']['sucess'] = 'Vous êtes maintenant connecté.';
        if($_POST['remember']){
            $remember_token = str_random(250);
            $pdo->prepare('UPDATE users SET remember_token = ? WHERE id = ?')->execute([$_remember_token, $user->id]);
            setcookie('remember', $user->id . '==' . $remember_token . sha1($user->id . 'raton-laveurs'), time() + 60 * 60 * 24 * 7);
            header('Location: account.php');
            exit();
        }else {
            header('Location: account.php');
            exit();
        }
    }else{
        $_SESSION['flash']['danger'] = 'Identifiant ou mot de passe incorrect';
    }
}
?>

functions.php

function reconnect_from_cookie(){
    if(session_status() == PHP_SESSION_NONE){
        session_start();
    }
    if(isset($_COOKIE['remember']) && !isset($_SESSION['auth'])){
        require_once 'db.php';
        if(!isset($pdo)){
            global $pdo;
        }
        $remember_token = $_COOKIE['remember'];
        $parts = explode('==', $remember_token);
        $user_id = $parts[0];
        $req = $pdo->prepare('SELECT * FROM users WHERE id = ?');
        $req->execute([$user_id]);
        $user = $req->fetch();
        if($user){
            $expected = $user_id . '==' . $user->remember_token . sha1($user_id . 'raton-laveurs');
            if($expected == $remember_token){
                session_start();
                $_SESSION['auth'] = $user;
                setcookie('remember', $remember_token, time() + 60 * 60 * 24 * 7);
            }else{
                setcookie('remember', null, -1);
            }
        }else{
            setcookie('remember', null, -1);
        }
    }
}

Merci d'avance.

1 réponse


Hello,

Vérifie dans un premier temps que le token envoyé dans le mail est égale au token enregistré en base.
Je pense que le soucis vient de la taille du champs en base. Tu génère un string de 60 char, alors que peut être ton token ne peut pas dépasser les 50 en base (je dit ça au pif).

En ce qui concernant le remember_token, il est enregistré dans les cookies et non en base. Donc vérifie les cookies ;)

PS: Move ton sujet dans 'PHP'