$wpdb->Prepare逃逸太多了吗?如何正确使用它?

时间:2014-04-04 作者:Hexodus

我对$wpdb->prepare感到非常困惑。我想用它来清理用户输入,但结果是它破坏了查询。我无法想象它是如何工作的,但我无法找出我做错了什么。请耐心点,给我指出解决方案。下面的代码只是一个简单的示例,用于演示,目的是明确出现了什么问题以及如何出错。Later there will be user input 正在馈送此查询。

当我省略了“准备并使用sprintf”时,这个示例很有效:

global $wpdb;
$mydb = new \\wpdb( "My_Login" ,"My_PW" , "My_Custom_DB" ,"localhost"); //wpdb instance for my custom db

$tablename = "books";
$sort_direction = "DESC";
$limit = 5;   
$sqlquery = sprintf( "SELECT * FROM %s ORDER BY datum %s LIMIT %d", $tablename, $sort_direction, $limit );

$res = $mydb->get_results( $sqlquery );
echo "<br>".$sqlquery."<br>";
var_dump($res);
var\\u dump()的输出是包含预期结果的正确数组。

$sqlquery的输出为:

SELECT * FROM books ORDER BY datum DESC LIMIT 5
这是正确的SQL。

现在我将使用prepare(这是唯一更改的行):

global $wpdb;
$mydb = new \\wpdb( "My_Login" ,"My_PW" , "My_Custom_DB" ,"localhost"); //wpdb instance for my custom db

$tablename = "books";
$sort_direction = "DESC";
$limit = 5;   
$sqlquery = $mydb->prepare( "SELECT * FROM %s ORDER BY datum %s LIMIT %d", $tablename, $sort_direction, $limit );

$res = $mydb->get_results( $sqlquery );
echo "<br>".$sqlquery."<br>";
var_dump($res);
var\\u dump()的输出为NULL

$sqlquery的输出为:

SELECT * FROM \'books\' ORDER BY datum \'DESC\' LIMIT 5
显然,表名和描述不应该用引号括起来。在我看来,这就是它失败的原因。我仔细检查了一下,这与实例化$wpdb无关。当我使用$wpdb时,转义结果是相同的。

发生了什么事,或者我做错了什么?请帮帮我。

1 个回复
最合适的回答,由SO网友:Otto 整理而成

你在这里犯的错误是首先准备这些物品。

只能通过prepare()运行“data”变量。您不运行表名、排序方向或限制。这些是SQL命令本身的一部分,它们不是指存储在数据库列中的信息的数据。

您的SELECT查询没有数据输入。。。因此,它没有任何可以准备的输入。

对于SELECT的特定情况,数据是WHERE子句中的内容。列=%s,依此类推。这是一段可能不安全的可变数据,因为它可能来自用户输入。因此,必须运行数据以确保其安全。但是如果您有一个用于订购的硬编码“DESC”,那么在prepare中运行它是没有意义的。这是“DESC”。现在很安全。只有您不知道它是什么的数据才可能是不安全的。

编辑:也就是说,如果数据确实来自用户输入,比如用户可以选择要显示的项目数,那么必须对数据进行清理。因此,可以通过prepare运行限制,因为它们是整数,可能来自用户选择“5”或“10”。

但是,您不允许用户直接输入表名或排序顺序。他们会选择一个方向来显示东西,但你会将其转换为ASC或DESC。他们不会直接选择“书籍”,但可能会从你解释为“书籍”的列表中进行选择。诸如此类的事情。

结束

相关推荐

WPDB查询-解密数据库数据

我试图使用WPDB从数据库中获取数据,但我一直在研究如何解密数据,例如。数据存储为:a:2:{i:0;s:2:“92”;i:1;s:2:“71”}我想要92&;71由于这是我的帖子ID,如何使用WPDB从DB获取该部分?到目前为止,我的代码是:$crosssells = $wpdb->get_results( \"SELECT * FROM $wpdb->postmeta WHERE _crosssell_ids != \'\' \"&#x