0

我知道这个问题已经被问了一百万次,但是今天(2013 年)在 SQL 语句中运行变量之前验证查询字符串的标准是什么?

例如,如果我通过 $_GET['id'] 从 url 接收到变量“id”:

$id = $_GET['id'];

...运行前我应该做什么:

SELECT * FROM users WHERE id="$id"

这够了吗:

$id = mysql_real_escape_string($_GET['id']);

...对于这个具体的例子?

4

3 回答 3

1

这无关紧要,因为在大多数常规情况下 id 都是整数。你必须使用:

$id = (int)$_GET['id'];

现在的标准方法是使用参数化查询/准备语句,这些语句在 MySQLi 和 PDO 的库中表示。

对于任何手动验证,您需要明智地考虑您希望收到此变量的内容。

在这种情况下,您只需要整数,没有别的。你不需要人们通过 ID -> 发送1 UNION SELECT ...它仍然是一个有效的字符串,并且 mysql_real_escape_string 不会对它做任何事情。

于 2013-04-15T16:24:11.167 回答
1

在这种情况下,最简单的验证就是强制转换为整数。

<?php

$id = (int) $_GET['id'];

$sql = "SELECT * FROM users WHERE id=$id";

然后,您不需要在 SQL 表达式中的变量周围加上引号。事实上,在某些情况下,在数字文字周围使用引号会扰乱 SQL 优化器,所以我总是很困惑为什么这么多人养成这种习惯。

如果您想进行更复杂的验证,请阅读PHP 的过滤器扩展

最后,在 SQL 中使用变量的更好(更简单、更快、更安全)的方法是使用查询参数。但是 PHP 的弃用mysql_*函数不支持查询参数,所以你应该学习mysqliPDO

于 2013-04-15T16:27:20.433 回答
0

您可能应该mysqli从 deprecated切换到mysql_可以利用mysql::prepare()它允许您使用占位符的位置:

$stmt = $mysqli->prepare("SELECT District FROM City WHERE Name=?");
$stmt->bind_param("s", $city);
$stmt->execute();

SQL 所能获得的安全性。

但是mysql_real_escape_string()足以防止 SQL 注入(只要将字符串括在引号中)。

于 2013-04-15T16:28:34.967 回答