我知道这个问题已被问了一百万次,但是今天(2013年)在SQL语句中运行变量之前验证查询字符串的标准是什么?
例如,如果我通过$ _GET ['id']从网址收到变量“id”:
$id = $_GET['id'];
......在跑步前我该怎么做:
SELECT * FROM users WHERE id="$id"
这就够了:
$id = mysql_real_escape_string($_GET['id']);
...对于这个具体的例子?
答案 0 :(得分:1)
这是无关紧要的,因为在大多数传统情况下,id是一个整数。你必须使用:
$id = (int)$_GET['id'];
现在的标准方法是使用在MySQLi和PDO的库中表示的参数化查询/预处理语句。
对于任何手动验证,您需要明智地考虑您希望收到此变量的内容。
就像在这种情况下,你只期望整数,没有别的。您不需要人们通过ID发送 - > 1 UNION SELECT ...
仍然是一个有效的字符串,mysql_real_escape_string将不会对它做任何事情。
答案 1 :(得分:1)
在这种情况下最简单的验证就是强制转换为整数。
<?php
$id = (int) $_GET['id'];
$sql = "SELECT * FROM users WHERE id=$id";
然后,您不需要在SQL表达式中的变量周围加引号。事实上,有些情况下,使用数字文字周围的引号会混淆SQL优化器,所以我总是很困惑为什么这么多人会养成这种习惯。
如果您想进行更复杂的验证,请阅读PHP's filter extension。
最后,在SQL中使用变量的更好(更简单,更快速,更安全)的方法是使用查询参数。但是,PHP已弃用的mysql_*
函数不支持查询参数,因此您应该了解mysqli或PDO。
答案 2 :(得分:1)
您可能应该从已弃用的mysql_
切换到mysqli
,在那里您可以利用允许您使用占位符的mysql::prepare()
:
$stmt = $mysqli->prepare("SELECT District FROM City WHERE Name=?");
$stmt->bind_param("s", $city);
$stmt->execute();
哪个和SQL一样安全。
但mysql_real_escape_string()
足以阻止SQL注入(只要将字符串括在引号中)。