我确实理解准备好的语句是寻求防止 SQL 注入的最终方法。但是,它们以有限的方式提供覆盖;例如,如果我让用户决定按操作的顺序(即,它是 ASC 还是 DESC?等),则准备好的语句没有覆盖。
我知道我可以将用户输入映射到一个预定义的白名单。但是,这只有在可以预先创建或彻底猜测白名单时才有可能。
例如,在我上面提到的情况下(ASC 或 DESC),这可以很容易地根据接受值列表进行映射和验证。但是不存在无法对照白名单验证部分 SQL 语句的情况吗?
如果存在这种情况,那么推荐的方法是什么?
如果我要使用底层数据库的内置转义实用程序(例如 mysql 的 mysql_real_escape_string)全面转义 user_input,我会在哪里失败?
我问这个问题的假设是我总是用引用的值构造我的 sql 语句——即使是整数......
让我们看看下面的例子并反思一下。
select {$fields} from {$table} where Age='{$age}' order by {$orderby_pref}
假设所有变量都是用户提供的。
如果我要 mysql_real_escape_string 上面 SQL 中的所有变量(而不是使用准备好的语句,它只涵盖了我的一半,迫使我为另一半提供白名单,它无济于事),它不是同样安全吗(并且更容易编码)?如果不是,在哪种输入场景中转义实用程序会失败?
$fields = mysql_escape($fields);
$table = mysql_escape($table);
$age = mysql_escape($age);
$orderby_pref = mysql_escape($orderby_pref);
select {$fields} from {$table} where Age='{$age}' order by {$orderby_pref}