2017-09-13 3 views
0

Je suis un peu confus au sujet de Prepared Statements en PHP, je surveille le tutoriel suivant sur youtube: https://www.youtube.com/watch?v=aN5KqxK1slcPHP: la préparation des états à l'intérieur d'un projet basé POO

Après que j'ai reçu la note suivante sur mon actuellement code source mysqli:

Vous êtes ouverts à SQL injections et devrait vraiment utiliser préparés déclarations au lieu de concaténer vos requêtes. Spécialement depuis vous n'échappez pas du tout aux entrées de l'utilisateur!

Ma question:

Comment puis-je préparer la déclaration puisque je crée la syntaxe de l'instruction dans ma classe registre et ne transmettre la déclaration à ma classe de base de données pour exécuter -il en utilisant la fonction execute_query? Est-ce que je juste préparer l'instruction à l'intérieur de la fonction execute_query et vérifier si c'est soit une déclaration du format INSERT ou SELECT, puis préparer les valeurs?

J'apprécie toute sorte de suggestions et de commentaires.

Mon code actuel ressemble à ce qui suit:

classe Registre:

<?php 
    class register extends database 
    { 
     function __construct($username, $password, $email) 
     { 
      $this->username = $username; 
      $this->password = password_hash($password, PASSWORD_DEFAULT); 
      $this->email = $email; 
      $this->activation_id = $this->generateActivationId(); 
      $this->sender_email = '[email protected]'; 
      $this->activation_link = 'http://url.com/folder/activate.php?id=' . $this->activation_id; 
      $this->database = new database(); 
     } 

     function generateActivationId() 
     { 
      $generator = bin2hex(random_bytes(10)); 
      return $generator; 
     } 

     function registerAccount() 
     { 
      $this->database->connect(); 
      $user_lookup = $this->database->execute_query("SELECT * FROM users WHERE username = '" . $this->username . "'"); 

      if (mysqli_num_rows($user_lookup) > 0) 
      { 
       return false; 
      } 
      else 
      { 
       $this->database->execute_query("INSERT INTO users (username, password, email, activation_id) VALUES ('" . $this->username . "', '" . $this->password . "', '" . $this->email . "', '" . $this->activation_id . "')"); 
       $user_lookup_comfirm = $this->database->execute_query("SELECT * FROM users WHERE username = '" . $this->username . "'"); 

       if (mysqli_num_rows($user_lookup_comfirm) > 0) 
       { 
        $this->sendRegisterEmail(); 
        return true; 
       } 
       else 
       { 
        return false; 
       } 
      } 
     } 

     function sendRegisterEmail() 
     { 
      $subject = 'Registration - Activate your account'; 
      $message = 'Thank you for registering. Please activate your account by visiting the following site: <a href="' . $this->activation_link . '">Website link</a>'; 
      $headers = 'From: ' . $this->sender_email . "\r\n" . 
       'Reply-To: ' . $this->sender_email . "\r\n" . 
       'X-Mailer: PHP/' . phpversion(); 

      mail($this->email, $subject, $message, $headers); 
     } 
    } 
?> 

classe Database:

<?php 
    class database 
    { 
     function __construct() 
     { 
      $this->dBusername = 'xxx'; 
      $this->dBpassword = 'xxx'; 
      $this->dBhost = 'localhost'; 
      $this->dBdatabase = 'xxx'; 
      $this->dBcharset = 'utf8'; 
     } 

     function connect() 
     { 
      $mysqli = new mysqli($this->dBhost, $this->dBusername, $this->dBpassword, $this->dBdatabase); 

      if ($mysqli->connect_errno) 
      { 
       $this->_mysqli = false; 
      } 
      else 
      { 
       $mysqli->set_charset($this->charset); 
       $this->_mysqli = $mysqli; 
      } 
     } 

     function execute_query($sql) 
     { 
      if($results = $this->_mysqli->query($sql)) 
      { 
       return $results; 
      } 
      else 
      { 
       return false; 
      } 
     } 
    } 
?> 
+1

Cette classe 'database' ne fait * rien *. Débarrassez-vous de cela, utilisez directement une instance mysqli ou PDO. – deceze

+0

Donc je devrais juste créer une classe entière de gestionnaire de base de données qui crée une instance de mysqli et ensuite préparer les déclarations là et appeler ces fonctions de la classe de registre? – stackvisual

+2

Vous devriez simplement utiliser l'interface MySQLi ou PDO directement. Vous n'avez pas besoin d'un wrapper, il finit par causer plus de maux de tête que cela résout dans la plupart des cas. – Qirel

Répondre

-1
<?php 

class Config{ 

    private function Db(){ 
     $db = null; 

     $dsn = UR DSN; 
     $user = UR USER; 
     $pass = UR PASS; 
     try{ 
      $db = $pdo = new PDO($dsn, $user, $pass, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,PDO::ATTR_TIMEOUT => "10")); 
      return $db; 
     } catch(Exception $e){ 
      var_dump($e); 
     } 
     return null; 
    } 

    function execPreparedStatement($sql , Array $param = null){ 

      try{ 
      $db = $this->Db(); 
      if($db != null && ($db instanceof PDO)){ 

       $db->beginTransaction(); 
       $stm = $db->prepare($sql); 
       for ($i = 0 ; $i < count($param) ; $i++){ 
        $stm->bindValue($i + 1,$param[$i]); 
       } 

       $dat = $stm->execute(); 
       $db->commit(); 
       $stm = null; 
       $db = null; 
       return $dat; 
      } 
     } catch (PDOException $e) { 
      $db->rollBack(); 
      var_dump("<br><br>Error: ".$e->getMessage().' in '.$e->getFile().' on line '.$e->getLine(), $sql, $param); 
     } 

    } 


    function getPreparedStatement($sql , Array $param = null,$type = null) { 

     $db = $this->Db(); 
     if($db != null && ($db instanceof PDO)) { 
       $stm = $db->prepare($sql); 

       if(!empty($param)){ 
        for ($i = 0 ; $i < count($param) ; $i++){ 
         $stm->bindParam($i+1, $param[$i]); 
        } 
       } 

      try { 

       $stm->execute();     
       if($type) { 
        $dat = @$stm->fetchAll(PDO::FETCH_ASSOC); 
       } else { 
        $dat = @$stm->fetchAll(); 
       } 

       $stm = null; 
       $db = null; 
       return $dat; 

      } catch (Exception $e){     
       var_dump("<br><br>Error capturado: ".$e->getMessage().' in '.$e->getFile().' on line '.$e->getLine(),$sql,$param); 
      } 
     } 
    } 
} 

c'est une classe PDO u peut l'utiliser comme ceci

<?php 
$db = new Config(); 
// This is for an update 
$db->execPreparedStatement('update table set a = ?, b = ? where id = ?)', array(value1, value2, id)); 
// Select With out filter 
$data = $db->getPreparedStatment('select * from table'); 
// With Filter. 
$data = $db->getPreparedStatment('select * from table where id = ?', array(id)); 

c'est juste et par exemple je peux vous donner plus de feed-back si vous avez besoin. mais je pense que vous pouvez le faire sur votre propre