Sequelize用原生SQL查询时怎么防注入?

设计师红梅 阅读 25

我用Sequelize的sequelize.query()执行原生SQL,但用户输入会拼接到查询里,担心有SQL注入风险。比如下面这样写是不是不安全?

const userId = req.query.id;
const result = await sequelize.query(<code>SELECT * FROM users WHERE id = ${userId}</code>);

我知道Sequelize模型方法自带参数化,但原生查询该怎么正确传参才安全?试过直接拼字符串,但怕被注入。

我来解答 赞 7 收藏
二维码
手机扫码查看
2 条解答
极客晓娜
你这种拼接字符串的方式确实有SQL注入风险,我见过太多这种案例了。Sequelize原生查询的正确做法是用参数化查询,有两种方式:

第一种是位置参数,用问号占位,参数放数组里:
const result = await sequelize.query(
'SELECT * FROM users WHERE id = ?',
{ replacements: [userId] }
);


第二种是命名参数,用:name占位,参数放对象里:
const result = await sequelize.query(
'SELECT * FROM users WHERE id = :userId',
{ replacements: { userId } }
);


这两种方式Sequelize底层都会做参数化处理,相当于预编译SQL语句,用户输入会被当作纯数据处理而不是SQL代码。

另外有个细节要注意,如果查询特别复杂需要拼接SQL片段,可以用sequelize.escape()来转义输入:
const safeInput = sequelize.escape(userInput);


不过能用参数化就尽量用参数化,escape是最后的选择。后端处理用户输入永远要多留个心眼。
点赞 1
2026-03-10 08:01
Tr° 顺红
你这样直接拼接字符串确实会有注入风险。Sequelize.query()其实支持参数化查询,直接用它的占位符机制就行。

两种安全写法:

1. 用问号占位符:
const result = await sequelize.query(
'SELECT * FROM users WHERE id = ?',
{
replacements: [userId],
type: sequelize.QueryTypes.SELECT
}
);


2. 用命名参数(适合复杂查询):
const result = await sequelize.query(
'SELECT * FROM users WHERE id = :userId',
{
replacements: { userId: userId },
type: sequelize.QueryTypes.SELECT
}
);


Sequelize会自动帮你做参数转义。我平时都这么用,还没被注入过。其实ORM文档里都有写,就是很多人不看(摊手)
点赞
2026-03-05 09:03