用ORM框架就真的不会SQL注入了吗?

西门仙仙 阅读 2

最近在用Sequelize写Node.js后端,听说ORM能自动防SQL注入,但我还是有点不放心。比如我这样写:Model.findAll({ where: { name: userInput } }),如果userInput是用户直接传过来的字符串,会不会有风险?

之前试过故意传了个' OR '1'='1进去,结果数据库没崩,但不确定是不是Sequelize内部做了处理。有没有可能在某些写法下还是会绕过防护?比如用raw query或者拼接条件的时候?

我来解答 赞 3 收藏
二维码
手机扫码查看
1 条解答
IT人英歌
先说结论:正常用Sequelize的ORM写法是安全的,但你提到的raw query和某些拼接方式确实有坑。

你试的那个 ' OR '1'='1 没崩,是因为Sequelize内部用的是参数化查询,大概相当于这样:

SELECT * FROM users WHERE name = ? -- ' OR '1'='1 会被当作整个字符串传进去,不会被解析成SQL逻辑

所以标准写法 Model.findAll({ where: { name: userInput } }) 没问题。

但这几个地方容易翻车:

1. raw query
// 危险写法
Model.sequelize.query(SELECT * FROM users WHERE name = '${userInput}')

// 安全写法
Model.sequelize.query('SELECT * FROM users WHERE name = ?', { replacements: [userInput] })


这种直接拼字符串的raw query跟手写SQL没区别,该注入还是注入。

2. Sequelize.literal() 或 Sequelize.where()
// 危险写法
Model.findAll({
where: {
name: Sequelize.literal('${userInput}') // 直接拼进去
}
})

// 或者用Op.like时
Model.findAll({
where: {
name: {
[Op.like]: '%' + userInput + '%' // 尽量避免这样拼接
}
}
})


3. 字符串拼接的where条件
// 危险写法
const whereClause = "name = '" + userInput + "'"
Model.findAll({ where: Sequelize.literal(whereClause) })


总结一下:ORM的查询构建器是安全的,但一旦你用了raw query、literal()、或者自己拼字符串,那就跟裸写SQL没区别了。懒省事直接拼字符串的话,该注入还是注入。

日常开发尽量用对象形式写where条件,别碰literal(),除非万不得已必须用raw query时记得用参数绑定。
点赞
2026-03-13 12:03