我有一个访问者可以输入数据的表单,我想通过$ _POST变量将这些数据存储在mysql数据库中。我需要什么来阻止sql注入?
答案 0 :(得分:6)
使用 prepared statements 。
答案 1 :(得分:3)
我在2010年5月的PHP TEK-X会议上发表了关于这个主题的演讲,我试图介绍防御SQL注入的多种方法。没有一种方法在所有情况下都是最好的,因此您应该学习多种方法并使用所有方法:
在将其插入SQL查询之前,验证用户输入或来自外部源的任何其他内容(甚至是您自己数据库中的数据)。例如,您可以使用PHP的filter扩展名或正则表达式。
强制外部内容格式正确。例如,(int) $_POST["userid"]
类型转换为内容为普通整数,因此可以安全使用。
在SQL表达式中包含动态内容代替文字值时,请使用带参数的预准备查询。请注意,PHP中的普通mysql
扩展名不支持查询参数 - 请使用PDO。我不使用mysqli
,因为它的API不一致且难以使用。
使用IN()
谓词时,不能将一个参数用于值列表。连接多个参数占位符,就像列表中的值一样多。这并不难,只需要一两行代码:
$sql = "SELECT ... FROM ... WHERE user_id IN ("
. join(",", array_fill(0,count($userid_list),"?")) . ")";
$pdoStmt = $pdo->prepare($sql);
$pdoStmt->execute($userid_list);
使用动态表名,列名或SQL关键字时,不能使用查询参数。您必须插入动态内容。但您可以使用白名单技术将不受信任的内容映射到合法,安全的标识符和关键字。
有关更多信息和示例,请参阅我的演示文稿SQL Injection Myths and Fallacies。
您也可能喜欢我的新书SQL Antipatterns: Avoiding the Pitfalls of Database Programming。我的书中有一章关于SQL注入。
答案 2 :(得分:0)
请仔细阅读,然后再进行一些搜索:
https://stackoverflow.com/questions/1973/what-is-the-best-way-to-avoid-sql-injection-attacks
答案 3 :(得分:-1)
您必须遵循一些规则,同时向查询添加任何数据,无论来自何处 - 来自用户或表单或任何内容。规则始终保持不变。
要向数据库发送查询,您有两个选项:
以常规方式构建查询,使其看起来与您可以在sql控制台中运行的SQL查询完全相同
要做到这一点,人们应该理解一整套规则,而不仅仅是“使用mysql_real_escape_string”。
规则如:
分别发送查询和数据 这是最优选的方式,因为它可以简化为“使用绑定”。所有字符串,数字和LIMIT参数都可以绑定 - 完全不用担心 使用此方法,您的查询将占位符按原样发送到数据库,绑定数据以单独的数据包发送,因此,它不会干扰。 它就像代码和数据分离。您发送与数据分开的程序(查询本身)。
上述所有内容仅涵盖数据插入。 但有时我们必须使查询更加动态,添加运算符或标识符 在这种情况下,每个动态参数都应该在我们的脚本中进行硬编码,并从该集合中选择 例如,要进行动态排序:
$orders = array("name","price","qty");
$key = array_search($_GET['sort'],$orders));
$orderby = $orders[$key];
$query = "SELECT * FROM `table` ORDER BY $orderby";
或动态搜索:
$w = array();
$where = '';
if (!empty($_GET['rooms'])) $w[]="rooms='".mesc($_GET['rooms'])."'";
if (!empty($_GET['space'])) $w[]="space='".mesc($_GET['space'])."'";
if (!empty($_GET['max_price'])) $w[]="price < '".mesc($_GET['max_price'])."'";
if (count($w)) $where="WHERE ".implode(' AND ',$w);
$query="select * from table $where";
在此示例中,我们仅向查询添加用户输入的数据,而不是字段名称,这些都是脚本中的硬编码。 对于绑定,算法非常相似
等等。