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

Langage PHP Discussion :

POO, injection JSQL


Sujet :

Langage PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    200
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 200
    Par défaut POO, injection JSQL
    Bonjour à tous,
    je me replonge un peu dans le code php que j'avais mis de coté pas mal de temps.
    Je n'ai pas de problème particulier à ce stade mais j'aimerai avoir votre avis sur deux points:
    • Est ce que j'ai bien compris selon vous les bases de la POO au regard du code ci-dessous ?
    • Est ce que selon le code si dessous protège suffisement des injections SQL ? sinon pour quelle raison SVP ?


    Voici le principe que j'ai adopté:

    à la saisie d'un pseudo et d'un mot de passe dans un formulaire par un utilisateur, je vérifie par l'intermédiaire d'une classe (FormValidator) et d'expressions régulières que les caractères utilisés sont conformes à ma politique de login/passe.
    Si les conditions sont respectées, j'ai une classe authentification (AuthVerif) chargée de vérifier la combinaison login/passe et de register une session si combinaison ok.

    Voici mon code:
    instanciation de mes classe:
    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
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
     
    <form action="/test" method="POST">
        <div>
            <div><label for="pseudo">Pseudo: </label><input type="text" name="pseudo" id="pseudo" value="<?= isset($_POST['pseudo'])?$_POST['pseudo']:''?>"</div>
            <div><label for="passe">Passe: </label><input type="text" name="passe" id="passe"></div>
            <div><input type="submit"></div>
        </div>
    </form>
    <?php
    if ($_POST) {
        $form = new \mvc\models\FormValidator();
        if($form->isNameValid($_POST['pseudo'],2,30) and $form->isPasswordValid($_POST['passe']))
        {
            $auth = New \mvc\models\AuthVerif($_POST['pseudo'],$_POST['passe']);
            if($auth->isLoginMatchesPassword())
            {
                if($auth->openSession()) {
                    echo "Session démarrée";
                }
            }
        } else {
            echo "Combinaison login/passe refusée";
        }
    }
    ?>
    Class FormValidator
    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
    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
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
     
    namespace mvc\models;
     
     
    /**
     * permet de vérifier la saisie des formulaires
     * Class FormValidator
     * @package mvc\models
     */
    class FormValidator extends Database
    {
        /**
         * FormValidator constructor.
         */
        public function __construct()
        {
            parent::__construct();
     
        }
     
        /**
         * permet de vérifier si la valeur est de type alpha uniquement
         * @param string $value valeur à tester
         * @return bool return true si alpha only
         */
        private function isAlpha(string $value)
        {
            return preg_match("#^[a-zA-Z]+$#",$value)?true:false;
        }
     
        /**
         * permet de verifier si la valeur est de type numérique uniquement
         * @param string $value valeur à tester
         * @return bool return true si numérique only
         */
        private function isNum(string $value)
        {
            return preg_match("#^[0-9]+$#",$value)?true:false;
        }
        private function contentNum(string $value)
        {
            return preg_match("#[0-9]+#",$value)?true:false;
        }
     
        /**
         * permet de vérifier si la valeur est de type alphanumérique uniquement
         * @param string $value valeur à tester
         * @return bool renvoie tru si alphanumérique only
         */
        private function isAlphaNum(string $value)
        {
            return preg_match("#^[a-zA-Z0-9]+$#",$value)?true:false;
        }
        /**
         * permet de renvoyé true si une chaine contient uniquement des alpha en début et fin et qui peut comtenir tiret, virgule ou espace
         * @param string $value valeur à tester
         * @return bool renvoie tru si alphanumérique only
         */
        private function isAlphaWithSpecialChar(string $value)
        {
            return preg_match("#^([a-zA-Z0-9]+)(([', -]{0,1})([a-zA-Z0-9]{1,}))*$#",$value)?true:false;
        }
     
        /**
         * permet de tester si la valeur fait au minimum un nombre donné de charactere
         * @param string $value valeur à tester
         * @param int $minChar nombre minimum de carctère souhaité
         * @return bool renvoie true si condition respectée
         */
        private function minCharNumber(string $value, int $minChar)
        {
            return strlen($value)>=$minChar?true:false;
        }
     
        /**
         * permet de tester si la valeur fait au maximum un nombre donné de charactere
         * @param string $value valeur à tester
         * @param int $maxChar nombre maximum de caractère souhaité
         * @return bool renvoie true si condition respectée
         */
        private function maxCharNumber(string $value, int $maxChar)
        {
            return strlen($value)<=$maxChar?true:false;
        }
     
        private function contentOneMajOrMore(string $value)
        {
            return preg_match("#[A-Z]+#",$value)?true:false;
        }
        private function contentOneMinOrMore(string $value)
        {
            return preg_match("#[a-z]+#",$value)?true:false;
        }
        private function contentOneSpecialChar(string $value)
        {
            return preg_match("#[@!&_\-\.\*\?\+\[\]\(\)\^\$]+#",$value)?true:false;
        }
     
        /**
         * permet de vérifier si la saisie d'un prénom est de type alpha et qu'elle respecte un nombre de charactère donné. il peut comporter des tirets, virgule ou espaces
         * @param string $value valeur du prénom à vérifier
         * @param int $minChar nombre minimum de charactère
         * @param int $maxChar nombre maximum de charactère
         * @return bool return true si conditions respectées
         */
        public function isNameValid(string $value, int $minChar, int $maxChar) {
            return ($this->isAlphaWithSpecialChar($value)&&$this->minCharNumber($value,$minChar)&&$this->maxCharNumber($value,$maxChar))?true:false;
        }
        private function acceptInPassword($value)
        {
            return preg_match("#[a-zA-Z0-9@!&_\-\.\*\?\+\[\]\(\)\^\$]#",$value)?true:false;
        }
        public function isPasswordValid($value)
        {
            return ($this->contentOneMajOrMore($value) and $this->contentOneMinOrMore($value) and $this->acceptInPassword($value) and $this->contentOneSpecialChar($value))?true:false;
        }
     
    }
    Classe AuthVerif
    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
    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
    <?php
     
     
    namespace mvc\models;
     
     
    /**
     * permet de vérifier la saisie des formulaires
     * Class FormValidator
     * @package mvc\models
     */
    class AuthVerif extends Database
    {
        private $pseudo;
        private $password;
        private $id;
        /**
         * AuthVerif constructor.
         */
        public function __construct($pseudoValue,$passValue)
        {
            parent::__construct();
            session_start();
            $this->pseudo=$pseudoValue;
            $this->password=$passValue;
        }
     
        /**
         * vérifie si l'utilisateur existe dans la table
         * @param string $pseudoValue valeur à chercher dans le champs de la table
         * @return bool renvoie true si la valeur existe dans le champs de la table
         */
        private function pseudoExistInDB()
        {
            $req=$this->query("SELECT * FROM membres WHERE pseudo = ?",[$this->pseudo]);
            return $res=$req->rowCount()!==0?true:false;
        }
     
        /**
         * vérifie si l'utilisateur existe et que le mot de passe correspond. Renvoie true si ok
         * @param string $loginValue valeur du login saisi
         * @param string $passValue valeur du mot de passe saisi
         * @return bool
         */
        public function isLoginMatchesPassword()
        {
            if ($this->pseudoExistInDB()) {
                $req=$this->query("SELECT id,pass FROM membres WHERE pseudo=?",[$this->pseudo]);
                $res=$req->rowCount();
                if ($res==1) {
                    $data=$req->fetch();
                    if(password_verify($this->password,$data->pass))
                    {
                        $this->id=$data->id;
                        return true;
                    } else {
                        return false;
                    }
                } else {
                    return false;
                }
            } else {
                return false;
            }
        }
        public function openSession() {
            if(!is_null($this->id))
            {
                $_SESSION["register"]=true;
                $_SESSION["pseudo"]=$this->pseudo;
                return true;
            } else {
                return false;
            }
        }
    }

  2. #2
    Expert confirmé
    Avatar de mathieu
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    10 711
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 10 711
    Par défaut
    d'habitude la 1re façon de laisser la porte ouverte à des injections sql est de construire une requête sql sous forme d'une chaine de caractère avec des données extérieures.
    ce n'est pas ce que vous faites, la requête avec des "?" est bien séparée des paramètres. mais ensuite on ne peut pas confirmer parce qu'on ne sait pas d'où vient cette classe Database ?

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    200
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 200
    Par défaut
    C'est vrai que je n'ai pas pensé joindre cette classe.

    La voila
    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
    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
    <?php
     
     
    namespace mvc\models;
    use \PDO;
     
    class Database
    {
        /**
         * @var string $pdo instance de PDO
         */
        protected $pdo=null;
        /**
         * @var string $error message d'erreur de connexion à la base
         */
        protected $error;
        public function __construct()
        {
            if($_SERVER['HTTP_HOST']=='base-test') {
                $db_name='***';
                $db_login='***';
                $db_pass='***';
                $db_host='localhost';
            } else {
                $db_name='***';
                $db_login='***';
                $db_pass='***';
                $db_host='***';
            }
            if (is_null($this->pdo)) {
                try {
                    $this->pdo=new PDO("mysql:dbname=$db_name;host=$db_host",$db_login,$db_pass,[PDO::MYSQL_ATTR_INIT_COMMAND=>'SET NAMES \'UTF8\'']);
                    $this->pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
                    $this->pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE,PDO::FETCH_OBJ);
                    return true;
                } catch(\PDOException $e)
                {
                     $this->error=$e->getMessage();
                    return false;
                }
            }
        }
        public function query($query,$params=false){
            $req=$this->pdo->prepare($query);
            try {
                ($params)?$req->execute($params):$req->execute();
            } catch (\PDOException $e)
            {
                echo $e->getMessage();
                return false;
            }
            return $req;
        }
    }

  4. #4
    Expert confirmé
    Avatar de mathieu
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    10 711
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 10 711
    Par défaut
    vous utilisez PDO donc vous êtes bien protégé contre les faille surprise. si par exemple un jour on découvre une faille avec un caractère spécial, il y a aura alors une nouvelle version de pdo et de php pour corriger cela et donc vous n'aurez pas besoin de modifier votre code.

    au niveau de la logique de votre code, cela me semble correct. j'ai juste remarqué une répètition à la vérification du mot de passe, d'abord vous appelez "pseudoExistInDB" qui va chercher un enregistrement et juste après vous cherchez le même enregistrement. donc il y a peut-être une économie de ressources qui peut être faite à cet endroit.

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    200
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 200
    Par défaut
    Merci pour ce retour j'en prends bonne note.
    pensez vous que preg_match est une bonne solution pour vérifier la saisie utilisateur et l'envoie de code malveillant éventuel (en plus des requêtes préparées)?
    je n'ai pas du tout utiliser de html entities mais selon moi cela sécurise avec preg_match. Je me trompe peut être.

  6. #6
    Expert confirmé
    Avatar de mathieu
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    10 711
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 10 711
    Par défaut
    Citation Envoyé par tyjez Voir le message
    pensez vous que preg_match est une bonne solution pour vérifier la saisie utilisateur et l'envoie de code malveillant éventuel (en plus des requêtes préparées)?
    cela peut permettre de vérifier que la données est dans un bon format, après il existe diverses façons de violenter du code (comme par exemple essayer d'accéder aux fichiers du système) donc il faudra peut-être faire d'autre tests.
    Citation Envoyé par tyjez Voir le message
    je n'ai pas du tout utiliser de html entities mais selon moi cela sécurise avec preg_match. Je me trompe peut être.
    la fonction htmlentities servait plutôt pour la génération de xml, vous confondez peut-être avec htmlspecialchars.
    https://www.php.net/manual/fr/functi...ecialchars.php
    cette fonction sert à générer du code html valide, ce n'est pas vraiment une fonction de protection si on a vérifié le format des données avant de les enregistrer dans une base de données.

Discussions similaires

  1. POO, injection de dépendance
    Par okoweb dans le forum Langage
    Réponses: 3
    Dernier message: 07/04/2015, 16h44
  2. [POO] C'est quoi une classe en claire...???
    Par Spack dans le forum Langages de programmation
    Réponses: 5
    Dernier message: 26/01/2009, 16h53
  3. Réponses: 16
    Dernier message: 06/06/2007, 13h42
  4. [langage] Pb POO perl
    Par loothoof dans le forum Langage
    Réponses: 4
    Dernier message: 26/05/2004, 13h08
  5. lier un cube à un objet (POO)
    Par Hypnos dans le forum OpenGL
    Réponses: 12
    Dernier message: 26/08/2003, 22h46

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