Comprendre, c'est apprendre.

ebaholic

ebaholic Le 17 avril 2018 à 11:29 (Édité le 25 janvier 2019 à 17:54)

Bonjour les pros.
Apprenti de 1er niveau, je m'essaye depuis un bon moment à la création d'un espace membre. Que ce soit entre les super tutos de Primx et ceux d''Openclassroom, je n'arrive pas à m'en sortir et à avoir ce que je veux (aucune urgence, juste du travail perso pour apprendre). Mélanger les tutos n'est peut-être pas recommandé, mais bon...
Donc je suis parti sur un autre modèle (dev-time pour ne pas vous le cacher) avec lequel je commence à m'en sortir avec mon apprentissage Primx et Openclass. Ce n'est peut-être pas élégant et respectueux vis à vis d'ici et je m'en excuse par avance, mais voici mon modèle .
Mes inscriptions se passent bien niveau de ma base de données, mais j'ai un souci au niveau des header (Location) que je ne pige. 

Sur incription.php, le formulaire (qui marche très bien et je remercie encore Primx pour ces tutos qui m'ont appris à bien interpréter le code). 
Le fichier inscription.php
<?php
session_start();
include('header.php');
const MIN_PSEUDO_LEN = 3;
const MAX_PSEUDO_LEN = 80;
const MIN_PASSWORD_LEN = 6;
$errors = [];
mb_internal_encoding('UTF-8');
if ('POST' == $_SERVER['REQUEST_METHOD']) {
    require('shared.php');
    if (array_key_exists('email', $_POST)) {
        if (!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
            $errors['email'] = "L'adresse email est invalide";
        } else {
            $stmt = $bdd->prepare('SELECT 1 FROM utilisateurs WHERE email = :email');
            $stmt->execute(['email' => $_POST['email']]);
            if (FALSE !== $stmt->fetchColumn()) {
                $errors['email'] = "Cette adresse email est déjà utilisée";
            }
        }
    } else {
        $errors['email'] = "L'adresse email est absente";
    }
    if (array_key_exists('login', $_POST)) {
        $login_length = mb_strlen($_POST['login']);
        if ($login_length < MIN_PSEUDO_LEN || $login_length > MAX_PSEUDO_LEN) {
            $errors['login'] = sprintf("La longueur du login doit être comprise entre %d et %d caractères", MIN_PSEUDO_LEN, MAX_PSEUDO_LEN);
        } else {
            $stmt = $bdd->prepare('SELECT 1 FROM utilisateurs WHERE login = :login');
            $stmt->execute(['login' => $_POST['login']]);
            if (FALSE !== $stmt->fetchColumn()) {
                $errors['login'] = "Ce pseudonyme est déjà utilisé";
            }
        }
    } else {
        $errors['login'] = "login est absent";
    }
    if (array_key_exists('mdp', $_POST)) {
        $mdp_length = mb_strlen($_POST['mdp']);
        if ($mdp_length < MIN_PASSWORD_LEN) {
            $errors['mdp'] = sprintf("La longueur du mot de passe doit être d'au moins %d caractères", MIN_PASSWORD_LEN);
        }
        if ($_POST['mdp'] != $_POST['mdpconfirm']) {
            $errors['mdpconfirm'] = "Le mot de passe et sa confirmation ne coïncident pas";
        }
    } else {
        $errors['mdp'] = "mot de passe est absent";
    }
    if (!$errors) {
        $insert = $bdd->prepare('INSERT INTO utilisateurs(login, email, mot_de_passe) VALUES(:login, :email, :mdp)');
        $insert->execute(['login' => $_POST['login'], 'email' => $_POST['email'], 'mdp' => password_hash($_POST['mdp'], $password_options['algo'], $password_options['options'])]);
        header('Location: connexion.php');
        exit;
    }
}
?>
<!DOCTYPE html>
<html>
    <head>
                
    </head>
    <body>
        <div class="container-fluid">
            <div class="row">
                <div class="col-xs-12">
<?php
if ($errors) {
    echo '<div class="alert alert-warning"><p>Veuillez corriger les erreurs ci-dessous afin de réaliser votre inscription :</p><ul><li>', implode('</li><li>', $errors), '</li></ul></div>';
}
?>
<form method="post" action="">
<fieldset><legend>Inscription :</legend>
<div class="form-group <?php if (array_key_exists('login', $errors)) echo 'has-error'; ?>">
<label for="login">Choisissez un pseudo :</label>
<input type="text" id="login" name="login" class="form-control" value="<?php if (array_key_exists('login', $_POST)) echo htmlspecialchars($_POST['login']); ?>" />
</div>
<div class="form-group <?php if (array_key_exists('email', $errors)) echo 'has-error'; ?>">
<label for="email">Indiquez votre Email :</label>
<input type="email" id="email" name="email" class="form-control" value="<?php if (array_key_exists('email', $_POST)) echo htmlspecialchars($_POST['email']); ?>" />
</div>
<div class="form-group <?php if (array_key_exists('mdp', $errors) || array_key_exists('mdpconfirm', $errors)) echo 'has-error'; ?>">
<label for="mdp">Mot de passe :</label>
<input type="password" id="mdp" name="mdp" class="form-control" value="" /></div>
<div class="form-group <?php if (array_key_exists('mdpconfirm', $errors)) echo 'has-error'; ?>">
<label for="mdpconfirm">Confirmation du mot de passe :</label>
<input type="password" id="mdpconfirm" name="mdpconfirm" class="form-control" value="" /></div>
</fieldset><input type="submit" class="btn btn-default" />
</form>
</div></div></div>
</body>
</html>


Après validation, on est renvoyé sur une page connexion.php


<?php
session_start();
$fail = FALSE;
if ('POST' == $_SERVER['REQUEST_METHOD']) {
    require('shared.php');
    $stmt = $bdd->prepare('SELECT * FROM utilisateurs WHERE login = :login');
    $stmt->execute(['login' => $_POST['login']]);
    if ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
    if (password_verify($_POST['password'], $row['mot_de_passe'])) {
      $_SESSION['id'] = $row['id'];
        if (password_needs_rehash($row['mot_de_passe'], $password_options['algo'], $password_options['options'])) {
         $stmt = $bdd->prepare('UPDATE utilisateurs SET mot_de_passe = :new_hash WHERE id = :id');
           $stmt->execute(['id' => $row['id'], 'new_hash' => password_hash($_POST['password'], $password_options['algo'], $password_options['options'])]);
  }
   header('Location: index.php');
   exit;
   } 
else 
{
  $fail = TRUE;
}
}
else 
{
 $fail = TRUE;
}
}
?>
<!DOCTYPE html>
<html>
    <head>
        
    </head>
    <body>
   <?php include('header.php'); ?>
        <div class="container-fluid">
            <div class="row">
                <div class="col-xs-12">
<?php
if ($fail) {
    echo '<p class="alert alert-info">Aucun utilisateur ne correspond à ce couple login/mot de passe.</p>';
}
?>
 <form class="form-horizontal" method="POST">
 <div class="form-group">
 <label for="login" class="col-sm-2 control-label">Login</label>
  <div class="col-sm-10">
  <input type="text" class="form-control" id="login" name="login"></div>
  </div>
  <div class="form-group">
  <label for="password" class="col-sm-2 control-label">Mot de passe</label>
  <div class="col-sm-10">
  <input type="password" class="form-control" id="password" name="password"></div>
  </div>
  <div class="form-group">
  <div class="col-sm-offset-2 col-sm-10">
  <button type="submit" class="btn btn-default">Se connecter</button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </body>
</html> 


Là aussi, on se connecte bien, et on est renvoyé sur la page index.php. La petite clé dans ma barre d'adresse (chrome), m'indique bien que je suis connecté. Mais si je navigue vers une autre page, comme une page test.php 

<?php
session_start();
?>
<p>test</p>

Je perd la connexion (je n'ai plus la clé dans ma barre d'adresse), que je perd aussi si je rafraîchi la page index après y être avoir été envoyé. 
Pourtant je suis bien reconnu grâce à un echo sur la page profil.php

<?php
session_start();
include('header.php');
if (!isset($_SESSION['id'])) {
    header('Location: connexion.php');
    exit;
} else {
    require('shared.php');
    $stmt = $bdd->prepare('SELECT * FROM utilisateurs WHERE id = :id');
    $stmt->bindParam('id', $_SESSION['id'], PDO::PARAM_INT);
    $stmt->execute();
    $user = $stmt->fetch();
    echo 'Bienvenue ', htmlspecialchars($user['login'], ENT_NOQUOTES);
} ?>



Est-ce qu'un 
session_start();

n'est pas censé me faire suivre la connexion ? 
Les header(location...) sont simple, mais je n'arrive pas à trouver la logique dans leur utilisation (surtout lorsque il s'agit de faire appel à la même page).
Je ne cherche pas à ce que l'on me ponde directement une correctement, je cherche aussi à comprendre. 
Et je vous envie de maîtriser tout ça aussi bien.
 Merci à vous. 


Le fichier shared.php
<?php
# hachage mots de passe
$password_options = [ 'algo' => PASSWORD_DEFAULT, 'options' => [ 'cost' => 12 ] ];
# connexion à la base de données
$bdd = new PDO('mysql:host=localhost;dbname=dev;charset=utf8', 'root', '');
$bdd->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); ?>
Balatharas

Balatharas Le 18 avril 2018 à 15:55

C'est vrai que c'est agréable de voir quelqu'un qui veut avant tout comprendre, et pas qu'on lui balance un code tout beau tout propre.
Je tiens néanmoins à souligner que Dev-Time à un "passé" un peu malhonnête. Je fais parti d'une équipe de rédaction du même genre que DevTime, Skilldevice (no-pub), en tout cas j'y ai écris des tuto. SD date de + longtemps que DevTime. Mais un jour je me suis rendu sur leur site, et j'ai été pas mal surpris... Ils avaient tout simplement pris des copier coller de nos articles, ils n'ont même pas pris la peine de changer des mots, c'était vraiment identique. On est allés leur parler calmement, mais qu'est-ce qu'ils ont fait ? Ils ont modifié la date de publication de leur copier coller, et répondu "Non, c'est vous qui avez copier coller"... Honteux.. Bref !

La petite clé est je crois le signe que tu as demandé à Chrome de garder en mémoire les identifiants pour pré-remplir les champs de connexions, rien de +. Si elle disparaît ça ne change rien il me semble, tant que ton session_start() est là tu peux récup les données de la session utilisateur.
ebaholic

ebaholic Le 18 avril 2018 à 16:37 (Édité le 18 avril 2018 à 16:37)

Merci de ta réponse, qui en plus me fait me rendre compte comment je suis sot.  Oui, cette petite clé, je la connais par coeur et j'étais tellement obnubilé par mon truc que je ne les pas reconnue. 

Donc, j'y vais à taton : A partir du moment où l'on a session_start() (qui doit être placé tout en haut avant tout code html) sur un fichier, celui-ci fait son boulot de "faire" suivre les données de l'utilisateur. Donc si on veut que cela soit le cas sur tout le site, on le met sur toute les pages. Il fait suivre les données, qu'elle soient en GET ou en POST.

Est-ce que jusque là, je suis dans le bon ? 😁
Balatharas

Balatharas Le 19 avril 2018 à 18:47

Alors non, les données POST sont transmises avec un formulaire de méthode POST. Les GET sont les paramètres uniquement dans l'url: https://primfx.com/profil.php?pseudo=ebaholic
Le session_start fait suivre les var superglobales $_SESSION
Il faudrait que tu vérifies (PHP) tu me met le doute haha
Vous devez être connecté pour poster une réponse. Se connecter ou Créer un compte