2017-06-13 50 views
1

此代碼有效,但由於將GET參數連接到查詢中似乎不安全。我是串聯的,因爲我需要WHERE子句中的動態數量的參數,它可以是不同類型的(IN,正常比較條件)。如何使用動態數量的參數來準備語句?

如何從不同類型的WHERE條件的動態數字中準備安全語句?

class myclass 
{ 
    public function index($where_clause = 1) 
    { 
     // db connection (using pdo) 
     $stm = $this->dbh->query("SELECT COUNT(amount) paid_qs FROM qanda $where_clause"); 
     $ret = $stm->fetch(PDO::FETCH_ASSOC); 
     // do stuff 
    } 
    public function gen_where_clause() 
    { 
     $where_clause = ''; 
     if (isset($_GET['c']) || isset($_GET['t'])) 
     { 
      $where_clause = 'WHERE '; 
      if (isset($_GET['c'])) 
      { 
       $where_clause .= 'cat = ' . $_GET['c']; 
      } 
      if (isset($_GET['t'])) 
      { 
       if (isset($_GET['c'])) 
       { 
        $where_clause .= $where_clause . ' AND ' 
        } 
       $where_clause .= 'tag IN(' . $_GET['t'] . ')'; 
      } 
     } 
     return $this->index($where_clause); 
    } 
} 
+0

@AbraCadaver你爲什麼把我的問題標記爲重複?您提供的重複鏈接完全不同。 –

+1

'$ where_clause。='cat =:cat';'或'$ where_clause。='cat =?';'等等......並在稍後準備。 – AbraCadaver

+0

@AbraCadaver在你的情況下,我必須添加多個條件來準備和綁定值,這是我真實代碼中的噩夢。由於我有幾個參數。 –

回答

1

我會在三方面解決這個問題:代碼的實際正確性,解決方案和更好的實踐。


守則

這段代碼實際上工作,mentioned有一些甚至阻止它實際上是運行在所有非常基本的語法錯誤。我會認爲這是一個簡化的錯誤,但是,即使串聯是錯誤的:(。=和字符串本身任何一項都將正常工作,既會破壞查詢)每次語句複製

$where_clause .= $where_clause . ' AND ' 

動態數字參數

具有參數的動態數量的問題是有趣的,並且根據需要可以是相當令人費解,但是在這種情況下,一個相當簡單的PARAM級聯可以讓你實現了動態參數數量爲suggested by AbraCadaver

更確切地說,當條件被添加到語句,單獨的SQL添加到聲明,和值的數組:

$sql .= 'cat = :cat'; 
$values[':cat'] = $_GET['c']; 

然後,您可以準備語句,並用正確的執行它參數。

$stmt = $pdo->prepare($sql); 
$stmt->execute($values); 

更好的實踐

如前所述,在這個問題上給出的代碼可能無法正常運行在所有的,所以我要強調的幾個基本原則,OOP,將極大地提高這個片段。

  • 依賴注入

數據庫連接應通過構造函數注入,而不是重新創建每次執行查詢時(就像它,如果你在index方法連接)。請注意,$pdo是私有財產。它不應該是公開的,可以被其他對象訪問。如果這些對象需要數據庫連接,則在其構造函數中注入相同的pdo實例。

class myclass 
{ 
    private $pdo; 
    public function __construct(PDO $pdo) { $this->pdo = $pdo; } 
} 
  • 流動

其中一個方法應該是私有的,由其他(公衆一個)呼籲,將收到的參數是需要運行的功能應有盡有。在這種情況下,似乎沒有涉及任何爭論,一切都來自$_GET

我們可以調整索引,以便它接受查詢的sql和值,但這三行很容易轉移到另一個方法。

private function index($sql, $values) 
{ 
    $stmt = $this->pdo->prepare($sql); 
    $stmt->execute($values); 
    return $stmt->fetchAll(); 
} 

那麼公衆gen_where_clause(我認爲是錯誤命名......它真的產生價值,而不是條款),可以安全使用,將產生的參數動態數量,保護您免受SQL注射。

public function gen_where_clause() 
{ 
    $sql = "SELECT COUNT(amount) AS paid_qs FROM qanda "; 
    $values = []; 
    if (isset($_GET['c']) || isset($_GET['t'])) 
    { 
     $sql .= ' WHERE '; 
     if (isset($_GET['c'])) 
     { 
      $sql .= ' cat = :cat '; 
      $values[':cat'] = $_GET['c']; 
     } 
     // etc. 
    } 
    return $this->index($sql, $values); 
} 
  • 過濾輸入

轉義值是不需要的,用於SQL注入保護即,使用參數化查詢時。然而,消毒您的輸入始終是一個正確的想法。在函數之外進行清理,然後將其作爲參數傳遞給「搜索」函數,從超全局$_GET中解耦函數。定義過濾參數不在本文的相當大範圍內,請參閱documentation

// global code 
// create $pdo normally 
$instance = new myclass($pdo); 
$inputs = filter_input_array(INPUT_GET, $args); 
$results = $instance->gen_search_clause($inputs); 
相關問題