Précédent   Forum des professionnels en informatique > PHP > PHP & SGBD > PHP & Oracle
PHP & Oracle Forum d'entraide sur Oracle avec PHP. Avant de poster -> FAQ Oracle et Cours Oracle
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 15/07/2008, 10h34   #1
Membre actif
 
Inscription : avril 2007
Messages : 483
Détails du profil
Informations personnelles :
Âge : 24

Informations forums :
Inscription : avril 2007
Messages : 483
Points : 189
Points : 189
Par défaut Eviter les injections sql oracle

Bonjour,

Je voudrais savoir s'il existe une fonction php ou une méthode pour éviter les injections sql depuis un formulaire classique vers une base de données oracle

Je sais qu'il existe une fonction php qui fait cela pour les bases de données MySQL mais je n'ai encore rien trouvé pour faire la même chose avec les bases de données oracle.

Quelqu'un s'est-il déjà penché sur la question ?

Merci d'avance pour vos réponses
Sh4dow49 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/07/2008, 15h07   #2
Membre confirmé
 
Inscription : janvier 2006
Messages : 178
Détails du profil
Informations personnelles :
Âge : 33

Informations forums :
Inscription : janvier 2006
Messages : 178
Points : 208
Points : 208
Le mieux est d'utiliser des requêtes préparées, car cela empêche toute injection SQL et de plus permet d'utiliser le cache de requêtes d'Oracle (Shared Pool) au mieux, et ce gratuitement .

En gros quelque soit le langage, il faut avec Oracle toujours utiliser des requêtes préparées si on veut une appli qui tienne la route avec pas mal d'utilisateurs. (je peux détailler si tu veux)

Et le top (à mon sens) c'est d'utiliser des procédures stockées PL/SQL appelées via des requêtes préparées.

Quelle API utilises-tu pour te connecter à Oracle : OCI8 ? PDO ?
rbaraer est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/07/2008, 15h12   #3
Membre actif
 
Inscription : avril 2007
Messages : 483
Détails du profil
Informations personnelles :
Âge : 24

Informations forums :
Inscription : avril 2007
Messages : 483
Points : 189
Points : 189
J'utilise OCI8

Si j'ai bien compris ce que tu me dis concerne les requetes que j'exécute lors du chargement d'une page, or ce que je voudrais c'est éviter les requetes SQL saisies dans les champs d'un formulaire

Ou bien je me trompe ^^"

A vrai dire je n'ai pas très bien compris tous ces termes que tu as dis (comme procédures stockées ou requetes préparées)

Je ne connais pas très bien oracle je l'utilise car on m'a demandé de créer une appli avec oracle pour abse de données, sinon j'utilise plus couramment MySQL pour les appli php.

Je veux bien que tu détailles plus s'il te plait ^^
Sh4dow49 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/07/2008, 16h08   #4
Membre confirmé
 
Inscription : janvier 2006
Messages : 178
Détails du profil
Informations personnelles :
Âge : 33

Informations forums :
Inscription : janvier 2006
Messages : 178
Points : 208
Points : 208
Pas de problème .

Une requête préparée est une requête SQL où on définit des emplacements pour chaque paramètre de la requête.

Code :
SELECT nom, prenom FROM Utilisateur WHERE IdUtilisateur = :nomutilisateur;
Ensuite on "bind" chaque emplacement à une variable PHP, en donnant le type du champ SQL.

Une procédure stockée est une fonction enregistrée sur le serveur de base de données, compilée. L'utilisation de SP (stored procedures) a de très nombreux avantages sous Oracle (moins sous MySQL) en termes de performances et de sécurité. Si tu souhaites en utiliser je pourrai te montrer des exemples, et tu peux notamment aller sur le forum PL/SQL de developpez.com. Par exemple : http://www.developpez.net/forums/sho...d.php?t=584065 où il y a une belle procédure

Avant un exemple, je te montre l'API que je me suis créée au-dessus d'OCI8 pour me simplifier grandement la tâche dans toutes mes pages PHP :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
<?php 
 
    include 'connexion.inc.php';
 
    define('NB_RES_PAR_PAGE', 10);
 
    function fct_bd_connexion($strTypeCnx = "ADMIN")
    {
        if ($strTypeCnx == "ADMIN")
        {
            $conn = oci_connect(ORA_CON_NOM_ADMIN, ORA_CON_MDP_ADMIN, ORA_CON_BD);
        }
        else if ($strTypeCnx == "SITE")
        {
            $conn = oci_connect(ORA_CON_NOM_SITE, ORA_CON_MDP_SITE, ORA_CON_BD);
        }
        fct_bd_gerer_erreurs(null, $conn, __FILE__, __LINE__, "erreurbd.php");
 
        return $conn;
    }
 
    function fct_bd_deconnexion($conn)
    {
        oci_close($conn);
    }
 
    function fct_bd_gerer_erreurs($bres, $res, $file, $line, $strPageErreur)
    {
        if (!$bres)
        {
            $err = $res ? oci_error($res) : oci_error();
            if (isset($err['message'])) 
            {
                //$m = htmlentities(substr($err['message'], strpos($err['message'], ":") + 2, strpos($err['message'], "\n") - strpos($err['message'], ": ") - 2));
                $m = htmlentities(substr($err['message'], strpos($err['message'], ":") + 2));
                //$m = htmlentities($err['message']);
                $_SESSION['msgerreur'] = $m;
                header ("Location: $strPageErreur");
                exit;
            } 
        }
    }
 
    function fct_bd_call_sp($conn, $statement, &$bindvars, $strPageErreur = "erreurbd.php")
    {
        $stid = oci_parse($conn, $statement);
 
        // On lie les variables PHP à la requête
        foreach ($bindvars as $b) 
        {
            // On crée une variable locale avec comme nom celui passé en paramètre
            $$b[0] = $b[1];  
            // oci_bind_by_name(resource, bv_name, php_variable, length, type)
            $r = oci_bind_by_name($stid, ":$b[0]", $$b[0], $b[2], $b[3]); 
            fct_bd_gerer_erreurs($r, $stid, __FILE__, __LINE__, "erreurbd.php");
        }
        $r = oci_execute($stid, OCI_DEFAULT);
 
        fct_bd_gerer_erreurs($r, $stid, __FILE__, __LINE__, "erreurbd.php");
 
        // puis on recopie les variables dans le tableau original pour récupérer
        // les valeurs en sortie des variables OUT et IN OUT
        for ($i=0; $i<count($bindvars); $i++)
        {
            $bindvars[$i][1] = $$bindvars[$i][0];
        }
 
        oci_free_statement($stid);
 
        fct_bd_gerer_erreurs($r, $stid, __FILE__, __LINE__, "erreurbd.php");
 
        return 1;
    }
 
    function fct_bd_creer_curseur($conn, $strPageErreur = "erreurbd.php")
    {
        $curs = oci_new_cursor($conn);
        fct_bd_gerer_erreurs($curs, $conn, __FILE__, __LINE__, "erreurbd.php");   
 
        return $curs;
    }
 
    function fct_bd_lire_curseur($curs, &$arrResults, $typefetch = OCI_FETCHSTATEMENT_BY_ROW, $strPageErreur = "erreurbd.php")
    {
        oci_execute($curs);
 
        $nbrows = oci_fetch_all($curs, $arrResults, null, null, $typefetch);
 
        if ($nbrows == false)
        {
            fct_bd_gerer_erreurs($nbrows, $curs, __FILE__, __LINE__, "erreurbd.php");
        }
 
        oci_free_statement($curs);
 
        return $nbrows;
    }
?>
Les fonctions les plus utiles sont fct_bd_call_sp qui exécute une requête (je l'ai appelée call_sp car perso je ne fais qu'appeler des procédures stockées )et fct_bd_lire_curseur qui lit un curseur et renvoie le tableau résultat.

Maintenant un exemple avec appel de procédure stockée qui renvoie deux curseurs, que l'on lit :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function fct_bd_membre_detailsprofil(
                $conn, $strEmail, &$arrDetailsProfil, 
                &$arrDetailsModifs, $strPageErreur = "presentation.php")
    {
        $curs_profil = fct_bd_creer_curseur($conn);
        $curs_modifs = fct_bd_creer_curseur($conn);
        $arrBindArgs = array();
 
        $strRequete = "BEGIN pkg_membre.DetailsProfil(:email, :cur_detailsprofil, :cur_detailsmodifs); END;";
 
        array_push($arrBindArgs, array('EMAIL', $strEmail, 150, null));   
        array_push($arrBindArgs, array('CUR_DETAILSPROFIL', $curs_profil, -1, OCI_B_CURSOR));
        array_push($arrBindArgs, array('CUR_DETAILSMODIFS', $curs_modifs, -1, OCI_B_CURSOR));
        fct_bd_call_sp($conn, $strRequete, $arrBindArgs, $strPageErreur);
 
        fct_bd_lire_curseur($curs_profil, $arrDetailsProfil, OCI_FETCHSTATEMENT_BY_COLUMN, $strPageErreur);
        fct_bd_lire_curseur($curs_modifs, $arrDetailsModifs, OCI_FETCHSTATEMENT_BY_COLUMN, $strPageErreur);
    }
- on crée les deux curseurs en PHP
- on initialise le tableau qui va contenir les variables liées (bind variables)
- on construit la requête avec les emplacements de variables
- on remplit le tableau des variables de liens
- on exécute la requête
- on lit les 2 curseurs

Grâce à l'API, le code est beaucoup plus concis qu'en OCI8 direct.

J'espère que c'est clair.
rbaraer est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/07/2008, 16h21   #5
Membre actif
 
Inscription : avril 2007
Messages : 483
Détails du profil
Informations personnelles :
Âge : 24

Informations forums :
Inscription : avril 2007
Messages : 483
Points : 189
Points : 189
Merci pour cette explication.

C'est relativement clair, même si je ne comprends pas tout ^^" (mais avec un peu de recherche sur les fonctions ça devrait aller mieux ! )

Je reviendrais te demander si j'opte pour cette solution et que je rencontre des soucis ^^
Sh4dow49 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/07/2008, 17h03   #6
Membre confirmé
 
Inscription : janvier 2006
Messages : 178
Détails du profil
Informations personnelles :
Âge : 33

Informations forums :
Inscription : janvier 2006
Messages : 178
Points : 208
Points : 208
Sinon tu peux aussi jeter un coup d'oeil sur PDO pour Oracle. PDO est une interface commune d'accès aux SGBD en PHP : tu utiliserais exactement le même code pour MySQL et pour Oracle. Les requêtes préparées sont très simples à utiliser avec PDO.

Par contre, tu seras un peu limité si tu utilises les procédures stockées (pas de retour de plusieurs curseurs en même temps par exemple ).

N'hésites pas si tu as d'autres questions.
rbaraer est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 21h14.


 
 
 
 
Partenaires

Hébergement Web