real_escape_string和prepare()之间的区别?

时间:2014-01-03 17:40:59

标签: php mysql sql security

prepare()对于我的大多数代码来说似乎有点乏味和不必要。如果我在SQL命令中发送一个字符串,为什么我不能用real_escape_string来清理它?有什么不同?这就是我一直在做的事情,它对SQL注入效果很好......谢谢。

1 个答案:

答案 0 :(得分:7)

在SQL注入防御中,转义与使用查询参数一样有效。

如果不能始终如一地执行这两种方法,这两种方法的效果也会降低。

这两种方法仅用于保护SQL表达式中的单个。它们不支持查询的其他动态部分。例如,如果要ORDER BY用户指定的列。查询参数和转义函数都不能处理。

所以基本上,这是一种风格和个人偏好的问题。

我更喜欢查询参数,因为我认为:

$sql = "INSERT INTO mytable (columna, columnb, columnc) VALUES (?, ?, ?)";
$stmt = $pdo->prepare($sql);
$stmt->execute([$a, $b, $c]);

比这更清楚:

$sql = "INSERT INTO mytable (columna, columnb, columnc) VALUES ('".mysqli_real_escape_string($conn, $a)."', '".mysqli_real_escape_string($conn, $b)."', '".mysqli_real_escape_string($conn, $c)."')";
mysqli_query($conn, $sql);

你不能认真地说,摆弄所有那些开放引号/密切引号和.字符串连接比使用带有查询参数的prepare()更容易。


重新评论一个带参数的假设query()函数。

首先,没有必要。一起使用prepare()和execute()是编写安全代码的一个小代价,并且坚持使用单个函数执行它,你只是听起来很懒惰。我想你不检查错误返回false的函数的返回值吗?

为了它的价值,编写一个包装函数来做这两件事很容易,因为PHP隐式支持varargs。

function myquery() {
  global $pdo;
  $params = func_get_args();
  $sql = array_shift($params);
  $stmt = $pdo->prepare($sql);
  $stmt->execute($params);
  return $stmt; // so we can fetch(), etc.
}