节点.JS 基于提供的参数的快速表单 SQL 选择查询



我正在使用查询字符串以 RESTful 的方式获取一组用于点的搜索参数:

www.api.com/products?name=apple&colour=red

www.api.com/products?name=apple&colour=red&尺寸=大

如您所见,并非所有参数都是必需的。

为了防止SQL注入,在将变量放入查询时,我必须使用占位符:

connection.query("SELECT * FROM products WHERE name= ? AND colour= ?",
    [
     req.body.name,
     req.body.colour
    ]

但是,如果偶尔也提供了 size 参数,如何动态创建不同的查询?为搜索列的所有组合编写条件似乎是一个糟糕的解决方案,必须有更好的方法来做到这一点。如何根据提供的搜索参数动态创建 SQL 查询(当然,我会使用 express-validator 单独检查它们的有效性,并且只允许正确的列名(?

只要您小心,就可以

安全地使用字符串连接来做到这一点:

const conditions = [];
const values = [];
if (req.query.name) { conditions.push(`name=?`); values.push(req.query.name); }
if (req.query.colour) { conditions.push(`colour=?`); values.push(req.query.colour); }
if (req.query.size) { conditions.push(`size=?`); values.push(req.query.size); }
connection.query(
  "SELECT * FROM products " + (conditions.length ? ("WHERE " + conditions.join(" AND ")) : ""),
  values,
);
但是,确保

values数组中的位置与查询中?的顺序匹配完全取决于您。也完全取决于你/你的团队来维护规则,只连接受信任的字符串,而不是意外地包含用户输入。

https://www.atdatabases.org/docs/sql 提供了一种安全的方式来构建这样的 SQL 查询。我会做这样的事情:

const conditions = [];
if (req.query.name) conditions.push(sql`name=${req.query.name}`);
if (req.query.colour) conditions.push(sql`colour=${req.query.colour}`);
if (req.query.size) conditions.push(sql`size=${req.query.size}`);
connection.query(sql`
  SELECT * FROM products ${
    conditions.length
    ? sql`WHERE ${sql.join(conditions, ' AND ')}`
    : sql``}
`);

与使用 knex 一样,@database/pg 或 @databases/mysql 驱动程序与 sql 标签相结合可防止您意外创建 SQL 注入漏洞,但它们也允许您继续使用实际的 SQL 语法,这增加了显着的灵活性。

我刚刚发现 Knex.js(knex 类似查询动态添加(是一个可接受的选项。

如果存在任何其他选择,请告知

最新更新