[PHP] Remplissage Dropdown
Bonjour à tous,
Tout d'abord, je commence tout juste dans le développement web, je m'excuse par avance pour mes approximations, méconnaissances et autres abus de langages. N'hésitez pas à me reprendre
Voici la partie de mon code qui me pose problème :
<?php
if(isset($_POST['btn_view']))
{
$id = $_POST['btn_view'];
$name = $_POST['name' . $id];
$customer = $_POST['customer'. $id];
$number = $_POST['number'. $id];
$state = $_POST['state'. $id];
$_SESSION["affair_id"] = $id;
$_SESSION["affair_name"] = $name;
$_SESSION["affair_customer"] = $customer;
$_SESSION["affair_number"] = $number;
$_SESSION["affair_state"] = $state;
header("Location: affair/affair.php");
}
echo '
<div class="dropright">
<img data-toggle="dropdown" src="./images/menu.png">
<div class="dropdown-menu">
<a class="dropdown-item" href="menu.php">Menu</a>';
$db = Database::connect();
$statement = $db->query('SELECT affair.id, affair.name, affair.customer, affair.number, affair.state, users_task.user AS user FROM affair INNER JOIN users_task ON users_task.affair = affair.id ORDER BY affair.id DESC');
while($item = $statement->fetch())
{
if($item['user']==$_SESSION["id"])
{
echo '
<form id="liste_header" action="header_left.php" role="form" method="post" enctype="multipart/form-data">
<input name="id'. $item['id'] . '" type="hidden" value="'. $item['id'] . '">
<input name="name'. $item['id'] . '" type="hidden" value="'. $item['name'] . '">
<input name="customer'. $item['id'] . '" type="hidden" value="'. $item['customer'] . '">
<input name="number'. $item['id'] . '" type="hidden" value="'. $item['number'] . '">
<input name="state'. $item['id'] . '" type="hidden" value="'. $item['state'] . '">
<button name="btn_view" value="'. $item['id'] . '" type="submit" class="dropdown-item" >'. $item['name'] .'</button>
</form>
';
}
}
echo '</div>
</div>
';
Database::disconnect();
?>
Il permet de remplir une dropdown en fonction d'une base de donnée MySQL. Cette partie fonctionne très bien.
Là où ça se gatte, c'est quand je clique sur un des choix de la dropdown, cela m'envoie bien sur la page demandée mais avec les données de la mauvaise ligne de la table...
Je ne comprends pas pourquoi ça ne fonctionne pas car j'ai déjà réalisé une programmation similaire à la seule différence que ce n'était pas avec une dropdown...
Si quelqu'un voit l'erreur que j'ai faite ce serait cool
En tout cas merci d'avance à ceux qui prendront du temps à mon sujet
A plus tard j'espère
Sam
Bonjour Sam,
Quelques remarques en observant ton code :
$id = $_POST['btn_view'];
$name = $_POST['name' . $id];
$customer = $_POST['customer'. $id];
$number = $_POST['number'. $id];
$state = $_POST['state'. $id];
$_SESSION["affair_id"] = $id;
$_SESSION["affair_name"] = $name;
$_SESSION["affair_customer"] = $customer;
$_SESSION["affair_number"] = $number;
$_SESSION["affair_state"] = $state;
Attention, il ne faut jamais faire confiance aux données renvoyées par des utilisateurs (voir par exemple
et vérifier la validité des données)
if($item['user']==$_SESSION["id"])
Si tu n'as besoin que des données d'un seul user, ajoute plutôt une clause WHERE pour éviter de récupérer les données de tous les utilisateurs (utilise une requête préparée).
Pour le reste j'ai un peu de mal à comprendre le format ta liste et pourquoi tu cherches à afficher toutes les données à l'avance dans ta liste ...
Si je devais faire une liste déroulante de choix, je ferais comme ceci :
<select name="ma_liste">
<option value="id_du_choix">Le choix</option>
<option value="id_du_choix">Le choix</option>
<option value="id_du_choix">Le choix</option>
<option value="id_du_choix">Le choix</option>
</select>
Une liste simple avec juste l'ID de la ligne, puis à la page suivante tu récupères les données de la ligne de l'ID choisi.
D'ailleurs, à moins que tu sois le seul utilisateur de ton outil, ça ne sert à rien d'entrer les données à l'avance dans le formulaire car il faudra de toute façon revérifier un minimum la validité de ces données à la page suivante (car il est très simple de changer les données d'un formulaire), donc autant récupérer des données fiables provenant de ta base de données directement à la page suivante (vérifie tout de même la validité de l'ID renvoyé).
Bon courage
Cordialement,
Bonsoir Sébastien,
Tout d'abord, merci pour ta réponse
Concernant ceci :
Attention, il ne faut jamais faire confiance aux données renvoyées par des utilisateurs (voir par exemple htmlspecialchars et vérifier la validité des données)
ces données ont été traitées au moment d'être rentrées dans ma base par cette fonction :
function checkInput($data)
{
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
Là, je ne fais que réutiliser ces données. Elles ne sont pas retouchées par les utilisateurs.
Ici, mon formulaire me sert à insérer des noms d'affaires, qui ont été préalablement rentrées par un utilisateur dans une page dédiée, dans ma liste déroulante en leur affectant leur ID et la fonction submit, pour que lorsque l'on clique dessus, on accède à la page "affair.php" qui affiche les données de l'affaire sur laquelle on a cliqué...
Je n'utilise peut être pas la bonne logique...
Il y a sûrement mieux à faire ?
Ici, mon formulaire me sert à insérer des noms d'affaires, qui ont été préalablement rentrées par un utilisateur dans une page dédiée, dans ma liste déroulante en leur affectant leur ID et la fonction submit, pour que lorsque l'on clique dessus, on accède à la page "affair.php" qui affiche les données de l'affaire sur laquelle on a cliqué...
Je ne suis pas sûr d'avoir bien tout compris mais je vais quand même essayer de te répondre
Là, je ne fais que réutiliser ces données. Elles ne sont pas retouchées par les utilisateurs.
Même si les données de ta base de données sont parfaitement fiables, le risque n'est pas là ...
Par exemple, si tu utilises ces données directement pour afficher les données d'une affaire :
$id = $_POST['btn_view'];
$name = $_POST['name' . $id];
$customer = $_POST['customer'. $id];
$number = $_POST['number'. $id];
$state = $_POST['state'. $id];
$_SESSION["affair_id"] = $id;
$_SESSION["affair_name"] = $name;
$_SESSION["affair_customer"] = $customer;
$_SESSION["affair_number"] = $number;
$_SESSION["affair_state"] = $state;
Si tu ne fais aucun contrôle d'aucune sorte avant d'afficher les données d'une affaire, cela revient à créer une faille importante permettant d'afficher potentiellement n'importe quelle affaire, car il est très simple de modifier les informations de ton formulaire et de changer les ID (en faisant par exemple un simple clic droit sur ton formulaire, inspecter et tu modifies le code HTML).
Pire encore, si tu utilises l'une des valeurs $_POST dans une requête SQL (non préparée), tu mets potentiellement ta base de données en danger (voir
pour mieux comprendre).
Il y a sûrement mieux à faire ?
Une possibilité :
Page 1 :
- tu crées ton formulaire avec la liste de choix d'ID que l'utilisateur peut afficher (le but est de renvoyer l'ID en page 2 et rien d'autre)
Page 2 :
- tu vérifies que l'utilisateur est toujours connecté
- tu vérifies la validité de l'ID (par exemple si c'est un entier, ou au moins faire un htmlspecialchars)
- tu vérifies aussi si cet utilisateur a le droit d'afficher les informations de l'affaire demandée (car rappelle-toi qu'il est facile de changer les données dans un formulaire)
- et enfin, tu affiches les données demandées
Page 2 = affair.php (inutile de renvoyer sur une page intermédiaire pour rediriger ensuite sur affair.php, affair.php peut très bien recevoir les données $_POST)
J'espère que ça t'aidera un peu et t'évitera quelques mauvaises surprises (failles exploitées)
Si tu ne fais aucun contrôle d'aucune sorte avant d'afficher les données d'une affaire, cela revient à créer une faille importante permettant d'afficher potentiellement n'importe quelle affaire, car il est très simple de modifier les informations de ton formulaire et de changer les ID (en faisant par exemple un simple clic droit sur ton formulaire, inspecter et tu modifies le code HTML).
Pire encore, si tu utilises l'une des valeurs $_POST dans une requête SQL (non préparée), tu mets potentiellement ta base de données en danger (voir injection SQL pour mieux comprendre).
Ah d'accord je n'avais pas du tout cette notion
Du coup, j'ai fait avec des liens <a> :
<?php
echo '
<div class="dropright">
<img data-toggle="dropdown" src="./images/menu.png">
<div class="dropdown-menu">
<a class="dropdown-item" href="menu.php">Menu</a>';
$db = Database::connect();
$statement = $db->query('SELECT affair.id, affair.name, affair.customer, affair.number, affair.state, users_task.user AS user FROM affair INNER JOIN users_task ON users_task.affair = affair.id ORDER BY affair.id DESC');
while($item = $statement->fetch())
{
if($item['user']==$_SESSION["id"])
{
echo '
<a class="dropdown-item" href="./affair/affair.php?id_affair='. $item['id'] . '">'. $item['name'] .'</a>
';
}
}
echo '</div>
</div>
';
Database::disconnect();
?>
C'est mieux ou pas ? Point de vue sécurité ? En tout cas comme ça ça marche comme je le souhaite ^^
Oui ça te simplifie grandement le code avec les liens
Mais contrôle quand même bien la validité de l'id $_GET['id_affair']
et si l'utilisateur a le droit d'afficher les données de cet ID car le risque est le même que pour la version $_POST.
Du genre, je déconnecte la personne si elle accède, en modifiant l'id dans l'url, à une affaire qu'elle n'a pas le droit c'est ça ?
Ah d'accord
Merci en tout cas
je vois que vous n'avez pas protégé vos entrées pour que votre projet soit risqué
Bonsoir tracikeel52,
Merci pour ton message :
je vois que vous n'avez pas protégé vos entrées pour que votre projet soit risqué
Je débute, peux-tu préciser et me donner un exemple avec le dernier bout de code que j'ai mis ?
Je te remercie,
A plus tard
Sam
Comme cette input
Non protégé
$name = $_POST['name' . $id];
protégé
$name = mysql_real_escape_string($_POST['name' . $id]);
J'avais fait une fonction pour "sécuriser" :
function checkInput($data)
{
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
J'imagine que ça ne suffit pas. Je le rajoute à la suite comme ceci ?
function checkInput($data)
{
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
$data = mysql_real_escape_string($data);
return $data;
}
Oui, c'est mieux qu'avant. Toutes vos entrées sont désormais securiser contre les vulnérabilités sql injection
Ok super je rectifie mon code ! Merci !