使用Codeigniter安全地转义MySQL中的动态表名

时间:2012-07-17 19:44:13

标签: php mysql security codeigniter activerecord

我面临一个小问题。我现在正在处理一个需要在MySQL中使用动态表名的应用程序。

基本上,我有一个基于多种因素(流派,播放时长,发布日期等)从数据库中选择专辑的过程 - 此过程的一部分允许用户创建一堆自定义过滤器..

自定义过滤器会向该选择条件中的所有相册的用户返回一个计数。然后将这些相册的ID存储在一个包含随机生成的哈希/序列号的表格中(例如albumSelect_20880f9c05d68a)

我是这样做的,因为我不想在一个字段中存储一个巨大的逗号分隔列表(真的很傻) - 而且我并不想把一个值数组发送到隐藏字段中我的HTML因为这会增加数据吞吐量(一次可能有数千行)

在CodeIgniter中,我使用Query Bindings来生成我的SQL查询,如下所示:

select * from artists where artistName = ? AND albumTitle = ?

当我参数化查询

时,查询会自动转义
$query = $this->db->query($sql,array("Singer","Album"));

现在是棘手的部分

如果我写我的查询看起来像这样:

$sql = "select albumid from albums where albumid in (select albumid from albumSelect_?)";
$this->db->query($sql,array('20880f9c05d68a'));

生成的查询变为:

select `albumid` from `albums` where `albumid` in (select `albumid` from `albumSelect_'20880f9c05d68a'`)

非常正确,但显然查询无效......

修改:更多信息

查询可能是更大查询的一部分,具体取决于用户选择的条件。 e.g。

$sql = "select albumid from albums where albumid in(select albumid from tags where tag = ?) AND albumid in(select albumid from albumSelect_?)";

我只是想知道是否有办法让这个工作,或者如果有人可以建议一个更好的选择..表名的连接显然是一个选项。

提前致谢!

戴夫

2 个答案:

答案 0 :(得分:1)

转义机制仅适用于数据字符串,不适用于模式名称。换句话说,仅适用于表的内容,而不适用于结构。因此,您必须自己将字符串粘贴到查询中,或者避免以这种方式使用表。 ?的查询模板对您没有帮助。

如果将字符串粘贴到表名中,则可以使用通常的PHP字符串连接机制。您应该额外确定,以便根据适当严格的正则表达式检查字符串,以避免SQL注入。确保真的只粘贴您生成的格式的单个随机字符串,而不是其他内容。

作为替代方案,您可以拥有一个包含所有选择的大表,并使用其他列来保存您的标识哈希,或使用其他一些合适的键来标识单个选择。这样,您就不必在正常操作期间修改数据库模式。我相信包括我在内的大多数开发人员宁愿通过程序代码避免这种修改。良好的数据库设计适用于固定架构。

答案 1 :(得分:0)

听起来我想要使用动态SQL。你可能不得不走prepared statements的道路。有了它们,您可以在字符串上调用PREPARE,然后调用EXECUTE。正常连接工作正常。

这应该允许您将SQL构建为字符串并执行它。如果将CodeIgniter的参数化与MySQL存储过程结合使用,则可以调用类似"CALL selectAlbums(?, ?)"的查询(假设selectAlbums是包含实际查询的PREPARE的存储过程),这将返回集合。

如果你想摆脱输出中的' s,请通过CONCAT引导参数,这将产生一个正常的字符串。