預處理語句是對SQL注入是非常有用的。
預處理語句和綁定參數
預準備語句是用於執行該方法的特徵(or similar)以高效率反复SQL語句。
準備好的語句的基本工作原理是這樣的:
- 準備:一個SQL語句的模板創建和發送到數據庫。 某些值未指定,所謂的參數(labeled "?") 例如:INSERT INTO MyGuests VALUES(?, ?, ?)
- 該數據庫將分析,編譯和執行的SQL語句模板查詢優化,並將結果但不執行
- 執行:在以後的時間,將應用程序綁定值參數,數據庫執行該語句。 因為它與不同價值觀想要應用程序可以執行該語句多次
相比於直接執行SQL語句,預處理語句具有兩個主要優點:
- 準備的語句作為減少對查詢的準備做一次解析時間(although the statement is executed multiple times)
- 綁定參數減少帶寬的服務器,因為你需要每次只傳送參數,而不是整個查詢
- 準備的語句是針對SQL注入是非常有用的,因為參數值,這些值在以後使用不同的協議來發送,不需要被正確轉義。 如果原始報表模板不是從外部輸入導出,不會出現SQL注入。
在庫MySQLi預處理語句
下面的示例使用準備的語句和在庫MySQLi綁定參數:
實施例(MySQLi with Prepared Statements)
<?php
$servername = "localhost";
$username = "username";
$password =
"password";
$dbname =
"myDB";
// Create connection
$conn = new mysqli($servername,
$username, $password, $dbname);
// Check connection
if ($conn->connect_error)
{
die("Connection failed: " . $conn->connect_error);
}
// prepare and bind
$stmt = $conn->prepare("INSERT INTO MyGuests (firstname, lastname, email)
VALUES (?, ?, ?)");
$stmt->bind_param("sss", $firstname, $lastname,
$email);
// set parameters and execute
$firstname = "John";
$lastname
= "Doe";
$email = "[email protected]";
$stmt->execute();
$firstname
= "Mary";
$lastname = "Moe";
$email = "[email protected]";
$stmt->execute();
$firstname = "Julie";
$lastname = "Dooley";
$email = "[email protected]";
$stmt->execute();
echo "New records created successfully";
$stmt->close();
$conn->close();
?>
代碼行以從上面的例子解釋:
"INSERT INTO MyGuests (firstname, lastname, email) VALUES (?, ?, ?)"
在我們的SQL,我們插入一個問號(?)我們希望在一個整數,字符串,雙或BLOB值來代替。
然後,看看在bind_param()函數:
$stmt->bind_param("sss", $firstname, $lastname, $email);
該功能結合了參數的SQL查詢,並告訴數據庫什麼的參數。 在"sss"的說法列出的數據類型的參數。 的性格告訴MySQL的參數是一個字符串。
參數可以為四種類型之一:
- 我 - 整數
- ð - 雙
- 秒 - 字符串
- b - BLOB
我們必須對這些每個參數之一。
通過告訴MySQL的期待什麼類型的數據,我們盡量減少SQL注入的風險。
注意:如果我們要插入外部源的任何數據(like user input) ,這是非常重要的數據被消毒和驗證。
在PDO預處理語句
下面的示例使用準備的語句和在PDO綁定參數:
實施例(PDO with Prepared Statements)
<?php
$servername = "localhost";
$username = "username";
$password =
"password";
$dbname =
"myDBPDO";
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname",
$username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE,
PDO::ERRMODE_EXCEPTION);
// prepare sql and bind
parameters
$stmt = $conn->prepare("INSERT INTO MyGuests (firstname, lastname, email)
VALUES (:firstname, :lastname, :email)");
$stmt->bindParam(':firstname', $firstname);
$stmt->bindParam(':lastname',
$lastname);
$stmt->bindParam(':email', $email);
// insert a row
$firstname =
"John";
$lastname = "Doe";
$email = "[email protected]";
$stmt->execute();
// insert another row
$firstname = "Mary";
$lastname = "Moe";
$email = "[email protected]";
$stmt->execute();
// insert another row
$firstname = "Julie";
$lastname = "Dooley";
$email = "[email protected]";
$stmt->execute();
echo "New records created successfully";
}
catch(PDOException $e)
{
echo "Error: " . $e->getMessage();
}
$conn = null;
?>