SQL預處理語句的使用及防注入

許多成熟的數據庫都支持預處理語句(Prepared Statements)的概念。它們是什麼東西?php

你能夠把它們想成是一種編譯過的要執行的SQL語句模板,可使用不一樣的變量參數定製它。數據庫

預處理語句具備兩個主要的優勢:框架

  • 查詢只須要被解析(或準備)一次,但可使用相同或不一樣的參數執行屢次。
    • 當查詢準備好(Prepared)以後,數據庫就會分析,編譯並優化它要執行查詢的計劃。
    • 對於複雜查詢來講,若是你要重複執行許屢次有不一樣參數的但結構相同的查詢,這個過程會佔用大量的時間,使得你的應用變慢。
    • 經過使用一個預處理語句你就能夠避免重複分析、編譯、優化的環節。
    • 簡單來講,預處理語句使用更少的資源,執行速度也就更快。
  • 傳給預處理語句的參數不須要使用引號,底層驅動會爲你處理這個。
    • 若是你的應用獨佔地使用預處理語句,你就能夠確信沒有SQL注入會發生。
    • 然而,若是你仍然在用基於不受信任的輸入來構建查詢的其餘部分,這仍然是具備風險的

正由於預處理語句是如此有用,它成了PDO惟一爲不支持此特性的數據庫提供的模擬實現。fetch

這使你可使用統一的數據訪問規範而沒必要關心數據庫自己是否具有此特性。優化

/*
使用預處理語句重複插入數據(1)
此示例演示了一個經過向命名佔位符代入一個name和一個value值來執行的INSERT查詢
*/
$stmt= $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)");
$stmt->bindParam(':name', $name);
$stmt->bindParam(':value', $value); //插入一行
$name= 'one';
$value= 1;
$stmt->execute();//使用不一樣的值插入另外一行
$name= 'two';
$value= 2;
$stmt->execute();

/*
使用預處理語句重複插入數據(2)
此示例演示了一個經過向用?表示的佔位符代入一個name和一個value值來執行的INSERT查詢
*/
$stmt= $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (?, ?)");
$stmt->bindParam(1, $name);
$stmt->bindParam(2, $value); // 插入一行
$name= 'one';
$value= 1;
$stmt->execute(); // 使用不一樣的值插入另外一行
$name= 'two';
$value= 2;
$stmt->execute();

/*
經過預處理語句獲取數據
此示例演示使用從表單獲取的數據爲關鍵值來執行查詢獲取數據。用戶的輸入會被自動添加引號,因此這兒不存在SQL注入攻擊的危險。
*/
$stmt= $dbh->prepare("SELECT * FROM REGISTRY where name = ?");
    if($stmt->execute(array($_GET['name']))) {
        while($row= $stmt->fetch()) {
        print_r($row);
    }
}

其實主流的PHP框架都支持Prepared Statements,並且要簡單不少。下面是ThinkPHP模型支持的例子:.net

// 實例化User模型
$model= D('User');

// 定義預處理傳入數據
$data['username'] = 'deeka';
$data['password'] = '123456';

// 數據預處理
if($model->create($data)){
    $model->add();
}

參考資料

相關文章
相關標籤/搜索