IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PHP & Base de données Discussion :

Protection du code et optimisation [MySQL]


Sujet :

PHP & Base de données

  1. #1
    Invité
    Invité(e)
    Par défaut Protection du code et optimisation
    Bonjour,

    J'ai regardé quelques tuto comme http://fmaz.developpez.com/tutoriels...omprendre-pdo/

    Voici l'ancienne version de ma 1ère requête SQL de ma page PHP:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    $post_name = trim($_POST['name']);
     
    $prep = $database->prepare("SELECT `ID`, `Name`
    FROM table_1
    WHERE `Name` LIKE \"%".$post_name."%\"
    ORDER BY `Name` ASC
    LIMIT 0, 10;");
     
    $prep->execute();
    $num_rows = $prep->rowCount();
    $result = $prep->fetch(PDO::FETCH_ASSOC);
    J'ai eu un peu de mal à sortir la variable de la requête (pour le bindValue) mais j'ai réussi. Avec les symbole "%" cela ne me trouvait aucun résultat. Il semble qu'on ne peut pas avoir les "%" dans la requête. Savez-vous pourquoi?
    Voici le nouveau code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    $post_name = trim($_POST['name']);
     
    $prep = $database->prepare("SELECT `ID`, `Name`
    FROM table_1
    WHERE `Name` LIKE :name
    ORDER BY `Name` ASC
    LIMIT 0, 10;");
    $prep->bindValue(':name', "%".$post_name."%", PDO::PARAM_STR);
     
    $prep->execute();
    $num_rows = $prep->rowCount();
    $result = $prep->fetch(PDO::FETCH_ASSOC);
    Reste-t-il quelque chose à faire pour ne pas avoir de problème de sécurité? L'injection SQL me fait peur mais apparemment l'api PDO (avec le prepare bien utilisé) permet d'éviter ces problèmes.

    S'il y a plusieurs résultats dans la 1ère requête, j'affiche une liste des résultats. S'il n'y en a qu'un seul, je refais la requête en récupérant plus de résultats comme dans la requête suivante (il y a 32 id et proba en tout).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    SELECT `ID`, `Name`, `id_1`, `proba_1`, `id_2`, `proba_2`
    FROM table_1
    J'avais pensé que c'était une bonne idée quand la 1ère requête renvoie trop de résultat. Mais je me demande si ce ne serais pas mieux de le faire dès le début ...

    Ensuite je regarde les "proba_x" et s'ils sont différents de "0" je passe une requête pour récupérer les noms associés dans une autre table. J'avais testé avec quelque chose comme le code suivant mais sans succès : il me manquait quelques résultats. J'avais peut être faire une erreur ou alors la requête était trop longue ? J'aurais ensuite associé la proba et le nom via du code php.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $prep = $database->prepare("SELECT `ID`, `Name`
    FROM table_2
    WHERE `ID` = ".$result_base[$id_1]."
    OR `ID` = ".$result_base[$id_2]);
    Je fait donc maintenant le code suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    $prep = $database->prepare("SELECT `ID`, `Name`
    FROM table_2
    WHERE `ID` = :id");
    for ($i = 1; $i <= 32; $i++)
    {
      $id_search = "id_".$i;
      $proba_search = "proba_".$i;
      if ( $result_base[$proba_search] != 0 )
      {
        $prep->bindValue(':id', $result_base[$id_search], PDO::PARAM_INT);
        $prep->execute();
        $result_nom = $prep->fetch(PDO::FETCH_ASSOC);
        echo round($result_base[$proba_search]*100, 2)."% : ".$result_nom['Name']."<br />\r\n";
      }
    }
    J'ai vu ceci dans la doc sur PDO:
    Outre le fait que vos paramètres sont bien protégés, l'avantage initial des requêtes préparées est la réutilisation du moule de la requête. En effet, le SGBD à déjà effectué une partie du traitement sur la requête. Il est donc possible de ré-exécuter la requête avec de nouvelles valeurs, sans pour autant devoir reprendre le traitement du départ; le découpage et l'interprétation ont déjà été fait !
    ...
    Dans ce type de cas de figure qui oblige souvent l'exécution de requêtes dans des boucles, les requêtes préparées représentent une optimisation à ne pas négliger.
    Est-ce donc gênant de remplacer une requête sql (donc un seul parcourt de la table) et du code php par 32 requête sql? Pour le moment, ça ne me plait pas trop ...

    Merci d'avance.
    Dernière modification par sabotage ; 03/06/2013 à 08h18. Motif: restauration

  2. #2
    Modérateur
    Avatar de sabotage
    Homme Profil pro
    Inscrit en
    Juillet 2005
    Messages
    29 208
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Juillet 2005
    Messages : 29 208
    Points : 44 155
    Points
    44 155
    Par défaut
    1 - PDO ne permet pas plus la protection contre les injections que l'extension mysql_ : si on ne fait pas une requête préparée ou qu'on n'utilise pas les paramètres, on se retrouve avec une requête non protégée.

    2 - Es-tu sûr d'avoir besoin de 64 colonnes ?
    Pour te donner un exemple, dans un modele relationnel, quand un utilisateur doit choisir disons 4 options on ne fait pas une table utilisateur avec
    user_id, login - nom - prénom - option 1 - option 2 - option 3 - option 4

    on fait une table utilisateur
    login- nom - prénom
    et une table option
    user_id, option
    N'oubliez pas de consulter les FAQ PHP et les cours et tutoriels PHP

  3. #3
    Invité
    Invité(e)
    Par défaut
    1 - Dans la nouvelle version de la 1ère requête j'utilise une requête préparé (enfin je crois). Cette version est bien protégé? (la 1ère version ne l'était pas c'est sûr)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    $prep = $database->prepare("SELECT `ID`, `Name`
    FROM table_1
    WHERE `Name` LIKE :name
    ORDER BY `Name` ASC
    LIMIT 0, 10;");
    $prep->bindValue(':name', "%".$post_name."%", PDO::PARAM_STR);
    2 - Oui j'ai bien besoin d'autant de colonne. Ca correspond à la probabilité et à l'id de drop d'un objet et il peut y avoir de 0 à 32 drop. La table existe déjà comme ça.

  4. #4
    Modérateur
    Avatar de sabotage
    Homme Profil pro
    Inscrit en
    Juillet 2005
    Messages
    29 208
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Juillet 2005
    Messages : 29 208
    Points : 44 155
    Points
    44 155
    Par défaut
    Ca correspond à la probabilité et à l'id de drop d'un objet et il peut y avoir de 0 à 32 drop.
    Donc si tu as 1 drop tu as 62 colonnes qui ne servent à rien.
    La table existe déjà comme ça.
    Ce n'est une bonne raison pour rien ça.
    D'après ce que je vois de ta deuxième partie de code, tu es en train de te compliquer la vie parce que ta base n'est pas bien structurée.
    N'oubliez pas de consulter les FAQ PHP et les cours et tutoriels PHP

  5. #5
    Invité
    Invité(e)
    Par défaut
    Ah oui, je viens de comprendre où tu veux en venir (mal compris ton exemple la 1ère fois).

    Effectivement, je pourrais créer une autre table avec 3 colonnes: `ID`, `id_drop`, `proba_drop`
    Il suffirait d'une requête sql pour y mettre les info nécessaires:
    `ID`, `id_1`, `proba_1`
    `ID`, `id_2`, `proba_2`
    etc ...

    J'avais fais pareil pour avoir le nom associé à l'id_1, id_2, ... (le nom pouvait être dans plusieurs tables). C'est donc plutôt simple à faire.

    Ca me permettra en plus de trier le résultat suivant la colonne proba.
    En plus je n'aurais pas besoin de repasser la 1ère requête pour extraire plus de colonne . Ce sera donc parfait comme ça

    Merci pour m'avoir guidé

    Il me reste plus qu'à savoir si la nouvelle version de la 1ère requête est assez sécurisée.

    [Edit]J'ai créé la nouvelle table, c'était rapide à faire.
    Pour le moment, ça ne me plait pas trop ...
    Maintenant, ça me plait beaucoup mieux.

    ps: j'ai rayé cette partie de mon 1er post vu qu'elle n'est plus d’actualité
    Dernière modification par Invité ; 01/06/2013 à 12h08.

  6. #6
    Invité
    Invité(e)
    Par défaut
    J'ai fait les tests suivants et ça a l'air d'être pas mal du tout niveau sécurité. Aucun des trois n'a retourné de résultat
    toto' --
    toto" --
    (SELECT `Name` FROM TABLE WHERE `ID` = 123)
    Donc ça doit être impossible de faire un insert ou un delete dans la base de donnée. Quelqu'un peu confirmer ça?

    ps: je parle de la nouvelle version de la 1ère requête

  7. #7
    Membre régulier
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juillet 2008
    Messages
    64
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Conseil

    Informations forums :
    Inscription : Juillet 2008
    Messages : 64
    Points : 98
    Points
    98
    Par défaut
    On ne va pas pouvoir confirmer à ta place.

    Si tu fais tes développements, tu dois avoir une base de test quelque part pour tester ce que tu fais (pas uniquement le code, mais bien une BDD séparée).

    T'as qu'à inclure une requête SQL dans ton input pour voir ce que ça donne, genre :

    Ce qui donnerait, sans protection :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    "SELECT [champs] FROM [table] WHERE login LIKE '' OR '' = '' "

  8. #8
    Invité
    Invité(e)
    Par défaut
    Je n'ai pas vraiment de base de test. Vu que je suis toujours en train de créer la base finale.
    Je ferais un gros coup de ménage quand tout sera ok.

    Pour les requêtes je n'ai que deux choix possibles suivant le mode choisi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT `Name` FROM `table` WHERE `Name` LIKE :name
     
    SELECT `Name` FROM `table` WHERE `ID` = :id
    J'ai testé avec le "or" ça a l'air d'être bon. De plus il semble prendre les quotes pour des caractères. Par contre si je met un "%" ça le prend bien en compte dans la requête LIKE.
    Au final ça fonctionne correctement.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. protection du code
    Par clarisse dans le forum Général VBA
    Réponses: 3
    Dernier message: 06/03/2007, 08h14
  2. protection du code source
    Par sam01 dans le forum Droit
    Réponses: 3
    Dernier message: 28/06/2006, 11h43
  3. Protection du code VB
    Par anikeh dans le forum Access
    Réponses: 2
    Dernier message: 30/05/2006, 18h54
  4. protection du code : tableaux dynamiques
    Par Tchaill39 dans le forum Langage
    Réponses: 6
    Dernier message: 12/01/2006, 21h42

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo