预处理语句是对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;
?>