8791 sujets

Développement web côté serveur, CMS

Salut à tous
Je ne vois pas comment sécurise mes requètes avec POO.
J'ai une fonction save qui à en paramètre un tableau contenant les doonées à sauvegarder.

<?php 
stdClass Object
(
    [name] => ff
    [slug] => ff
    [id] => 
    [content] => 
ff
 
 
    [online] => 0
    [type] => post
    [created] => 2012-06-03 02:12:56
)

Visiblement le code PHP passe mal..

<?php 
public function save($data){    
        $key = $this->primaryKey;
        $fields =  array();
        $d = array(); 
        foreach($data as $k=>$v){
            if($k!=$this->primaryKey){
                $fields[] = "$k=:$k";
                $d[":$k"] = $v; 
            }elseif(!empty($v)){
                $d[":$k"] = $v; 
            }
        }
        if(isset($data->$key) && !empty($data->$key)){
            $sql = 'UPDATE '.$this->table.' SET '.implode(',',$fields).' WHERE '.$key.'=:'.$key;
            $this->id = $data->$key; 
            $action = 'update';
        } else{
            $sql = 'INSERT INTO '.$this->table.' SET '.implode(',',$fields);
            $action = 'insert'; 
        }
 
        $pre = $this->db->prepare($sql); 
 
        $pre->execute($d);
 
        if($action == 'insert'){
            $this->id = $this->db->lastInsertId(); 
        }
    }

N’étant pas un expert avec POO j'ai suivi quelques tutos, visiblement il faut sécuriser les requêtes avec bindValue. Merci de votre future aide
Modifié par clementlanot (03 Jun 2012 - 21:04)
Dans cette fonction, il y a peu d’intérêt à utiliser bindValue.
On ne sait pas de quel type sont le contenu des champs de $data et on ne sait pas d'où vient le nom des champs de $data.

Le plus rapide (pas le plus performant) est de sécuriser $k et $key par une fonction similaire à mysql_real_escape_string donc par exemple rajouter un bête addslashes à $k et $key.

Sinon la valeur des champs ($v) est déjà protégée par la méthode execute: d’après la doc de execute, mettre un tableau associatif dans cette méthode est équivalent à utiliser la méthode bindParam avec PARAM_STR (à vérifier quand même).

foreach($d as $col => $val) {
    $pre->bindValue($col, $val); // équivalent à mysql_real_escape_string() mais en PDO
}
$pre->execute();
Bind sert juste à lier les données aux différents champs. Ça sert à quoi de faire un bindValue si tu as déjà une requête préparée et que ton tableau de données contient des index nommés correctement (comme dans la requête) ?

$pre->execute($data); // Fait un bind automatique des données du tableau $data.

@moust : l'équivalent pdo de *escape_string() c'est la méthode quote().
Modifié par jb_gfx (04 Jun 2012 - 19:19)
Donc si je résume,

En faisant un addslaches doit un quote() en POO mais requètes seront protégées.
Rien ne sert ne faire un bindValue()

C'est ça ? Smiley cligne
clementlanot a écrit :
Donc si je résume,

En faisant un addslaches doit un quote() en POO mais requètes seront protégées.
Rien ne sert ne faire un bindValue()

C'est ça ? Smiley cligne


Non, avec une requête préparée tes données sont protégées automatiquement. Pas besoin de faire un quote() en plus (et surtout pas un addslashes(), ça tu le laisses au placard ça sert plus à rien depuis 10 piges).
On peux voir ça sur plusieurs tutos :
Sur les forums, je lis souvent « avec PDO, pas besoin de sécuriser ses requêtes, ça le fait tout seul ». Ceci est faux.
Lis le tuto en entier... faut pas juste prendre un bout de phrase hors contexte. De plus aucun rapport avec ta question. Tu utilises des requêtes préparées donc tu n'aura pas de soucis d'injection SQL et tu n'a pas besoin de BindValue dans ton exemple.
Modifié par jb_gfx (04 Jun 2012 - 19:51)
Il utilise BindValue .
Mais je comprend pas comment marche les requètes préparés enfin je comprend pas en quoi sa protège, comment ça marche.. alors que escape_string je comprenais un peu mieux. Smiley langue
clementlanot a écrit :
Il utilise BindValue .


Non, dans le premier exemple il utilise un array passé à la méthode execute() (ce que tu as fait) :


<?php
$stmt = $pdo->prepare("SELECT * FROM membres WHERE nom = :nom");
$stmt->execute(array('nom' => $nom));


Et dans le 2eme il utilise BindValue en disant juste que c'est plus joli (n'importe quoi). Ça sert que pour les SGBD qui ont un typage fort. Bref super tuto...

a écrit :

Mais je comprend pas comment marche les requètes préparés enfin je comprend pas en quoi sa protège, comment ça marche.. alors que escape_string je comprenais un peu mieux.


C'est simple, dans une requête préparée tu ne mets pas directement tes données dans la requête. A la place tu nommes des emplacement dans la requête et tu dis à ta base de données que tout ce qui sera dans cet emplacement seront des données et ne fera pas partie du code SQL.

Comme ça peu importe si quelqu'un s'amuse à insérer des apostrophes ou autre, tout ce qui est à cet endroit sera considéré commet étant une donnée à lire ou à insérer dans la base et jamais comme du code.


SELECT * FROM membres WHERE nom = :nom


Peu importe ce que tu mets dans la variable qui remplacera l'emplacement ":pseudo", ça ne sera jamais interprété comme du code MySQL et ne pourra donc pas interférer sur ta requête.
Modifié par jb_gfx (04 Jun 2012 - 20:32)