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

Dav*_*ave 8 php mysql security activerecord codeigniter

我面临一个小问题.我正在研究一个需要在MySQL中使用动态表名的应用程序.

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

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

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

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

select * from artists where artistName = ? AND albumTitle = ?
Run Code Online (Sandbox Code Playgroud)

然后,当我参数化查询时,查询会自动转义

$query = $this->db->query($sql,array("Singer","Album"));
Run Code Online (Sandbox Code Playgroud)

现在是棘手的部分

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

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

生成的查询变为:

select `albumid` from `albums` where `albumid` in (select `albumid` from `albumSelect_'20880f9c05d68a'`)
Run Code Online (Sandbox Code Playgroud)

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

编辑:更多信息

查询可以是更大查询的一部分,具体取决于用户选择的条件.例如

$sql = "select albumid from albums where albumid in(select albumid from tags where tag = ?) AND albumid in(select albumid from albumSelect_?)";
Run Code Online (Sandbox Code Playgroud)

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

提前致谢!

戴夫

MvG*_*MvG 1

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

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

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