如果把用户输入的没有任何改动的放到SQL的查询语句中,很有可能会导致SQL注入,比如说下面的例子:
$unsafe_variable = $_POST[\'user_input\']; mysql_query("INSERT INTO `table` (`column`) VALUES (\'$unsafe_variable\')");
为什么会有注入漏洞呢?因为用户可以输入value\'); DROP TABLE table;#...然后查询语句就变成了这样:
INSERT INTO `table` (`column`) VALUES (\'value\'); DROP TABLE table;#...\')
可以采用PDO预处理语句加参数化查询方法预防SQL注入攻击:
参数化查询(Parameterized Query或Parameterized Statement)是指在设计与数据库链接并访问数据时,在需要填入数值或数据的地方,使用参数(Parameter)来给值,这个方法目前已被视为最有效可预防SQL注入攻击的攻击手法的防御方式。
除了安全因素,相比起拼接字符串的SQL语句,参数化的查询往往有性能优势。因为参数化的查询能让不同的数据通过参数到达数据库,从而公用同一条SQL语句。大多数数据库会缓存解释SQL语句产生的字节码而省下重复解析的开销。如果采取拼接字符串的SQL语句,则会由于操作数据是SQL语句的一部分而非参数的一部分,而反复大量解释SQL语句产生不必要的开销。
原理 : 在使用参数化查询的情况下,数据库服务器不会将参数的内容视为SQL指令的一部分来处理,而是在数据库完成SQL指令的编译后,才应用参数运行,因此就算参数中含有具破坏性的指令,也不会被数据库所运行。
举例:
// 实例化数据抽象层对象 $db = new PDO(\'pgsql:host=127.0.0.1;port=5432;dbname=testdb\'); // 对SQL语句执行prepare,得到PDOStatement对象 $stmt = $db->prepare(\'SELECT * FROM "myTable" WHERE "id" = :id AND "is_valid" = :is_valid\'); // 绑定参数 $stmt->bindValue(\':id\', $id); $stmt->bindValue(\':is_valid\', true); // 查询 $stmt->execute(); // 获取数据 foreach($stmt as $row) { var_dump($row); }