用ORM就真的不会SQL注入了吗? 迷人的志红 提问于 2026-02-25 09:44:19 阅读 32 安全 我最近在用 Sequelize 写接口,听说 ORM 能防 SQL 注入,但心里还是不踏实。比如下面这种写法: const user = await User.findOne({ where: { id: req.query.id } }); 如果用户传了个 '1 OR 1=1 --' 进来,会不会被拼成恶意 SQL?我看文档说参数会自动转义,但不确定是不是所有情况都安全,特别是用 sequelize.literal() 或者 raw query 的时候。 ORM注入SQL注入防护 我来解答 赞 9 收藏 分享 生成中... 手机扫码查看 复制链接 生成海报 反馈 发表解答 您需要先 登录/注册 才能发表解答 2 条解答 ___晓娜 Lv1 直接说结论:Sequelize的findOne这种写法是安全的,参数会自动转义,'1 OR 1=1 --' 传进去也不会有问题。 但你担心是对的,ORM防注入是有前提的: 第一种情况,用普通的查询方法比如findOne、findAll、create这些,Sequelize会自动用参数化查询,底层用的是PDO的预处理语句,你完全不用担心。 第二种情况就比较坑了——用sequelize.literal()或者直接写raw query。比如这样: const user = await User.findOne({ where: sequelize.literal(id = ${req.query.id}) }); 这就相当于直接拼接字符串了,用户传什么你就执行什么,OR 1=1 分分钟教你做人。 还有这种: const [results] = await sequelize.query(SELECT * FROM users WHERE id = ${req.query.id}); 同样危险。 正确的做法是:如果非要用literal,参数得自己手动转义,或者用sequelize.escape()。但更推荐的是尽量别用literal,需要动态字段的话用sequelize.where()和sequelize.fn()。 至于raw query,要用占位符: const [results] = await sequelize.query( 'SELECT * FROM users WHERE id = :id', { replacements: { id: req.query.id } } ); 这样Sequelize会自动处理转义。 总结一下:ORM不是万能的,用对了方法就很安全,但一旦用了literal或者自己拼字符串,就得自己负责防注入了。官方文档里也明确说了,literal的值不会被转义,需要开发者自己保证安全。 回复 点赞 2026-03-19 20:09 シ雯婷 Lv1 别被 ORM 的宣传忽悠了,它只是帮你挡掉大部分常见注入,不是万能盾牌。 你贴的这个写法是安全的:User.findOne({ where: { id: req.query.id } }),Sequelize 会把 req.query.id 当成参数绑定,不会直接拼进 SQL,哪怕你传 '1 OR 1=1 --',最后生成的 SQL 类似 WHERE id = '1 OR 1=1 --',数据库会把它当普通字符串匹配,不会执行逻辑,所以没问题。 但重点来了:sequelize.literal() 和 Sequelize.literal() 是危险区。比如: sequelize.query(SELECT * FROM users WHERE id = ${req.query.id}, { type: QueryTypes.SELECT }) 或者 where: { id: sequelize.literal('${req.query.id}') } 这种就是你自己拼字符串,ORM 不管你传了啥,直接塞进 SQL,注入风险自己扛。 再比如: User.findOne({ where: { name: sequelize.literal(LIKE '%${req.query.keyword}%') } }) 如果 req.query.keyword 是 %' OR 1=1 --,那就凉了。 总结下: 普通 where、order、include 这些字段值,ORM 都会转义,放心用; 一旦你用 literal、raw、手写 SQL 字符串拼接,就等于脱了裤子自己上,必须自己做严格校验或转义。 建议: - 能不用 literal 就别用 - 真要用,至少先 escape 一下,比如:sequelize.escape(req.query.id) - 关键参数类型校验别偷懒,比如 id 明确是数字就 Number(req.query.id),非数字直接 reject 复制过去试试: // 安全 User.findOne({ where: { id: "'1 OR 1=1 --'" } }) // 不安全 User.findOne({ where: { id: sequelize.literal("'1 OR 1=1 --'") } }) 前者生成 WHERE id = '''1 OR 1=1 --''',后者直接变成 WHERE id = '1 OR 1=1 --',区别自己悟。 回复 点赞 8 2026-02-25 10:01 加载更多 相关推荐 1 回答 42 浏览 用ORM框架就真的不会SQL注入了吗? 我最近在Vue项目里用TypeORM做后端数据查询,听说ORM能防SQL注入,但心里还是没底。比如下面这种写法安全吗? <script setup> import { getReposit... 迷人的晨旭 安全 2026-03-24 16:54:22 2 回答 51 浏览 用ORM框架就真的不会SQL注入了吗? 最近在用Sequelize写Node.js后端,听说ORM能自动防SQL注入,但我还是有点不放心。比如我这样写:Model.findAll({ where: { name: userInput } }... 西门仙仙 安全 2026-03-13 11:38:19 2 回答 94 浏览 TypeORM里用Raw写SQL会有注入风险吗? 我最近在用TypeORM的Raw函数拼接查询条件,但担心这样会不会有SQL注入漏洞?比如下面这段代码: const users = await getRepository(User) .find({ ... 一家淼 安全 2026-03-06 00:28:21 1 回答 45 浏览 SQLMap测试时怎么判断是否存在SQL注入? 我用 SQLMap 测试一个登录接口,但返回结果不太确定是不是真的有注入点。比如运行 sqlmap -u "http://example.com/login" --data="username=adm... 司空俊鑫 安全 2026-03-25 14:47:24 2 回答 33 浏览 前端传数字ID到后端,做类型检查能防SQL注入吗? 我在写一个用户信息查询功能,前端传了个用户ID给后端接口。听说只要确保这个ID是数字就能防止SQL注入,是真的吗? 我试过在前端用typeof id === 'number'判断,但发现用户还是可以通... a'ゞ翌菡 安全 2026-03-03 20:25:18 1 回答 40 浏览 前端请求后端接口时,错误信息会不会导致SQL注入风险? 我最近在做登录功能,后端用的是Node.js + MySQL。之前听说如果错误信息暴露太多,可能会被用来做SQL注入攻击。我现在catch到数据库错误就直接把err.message返回给前端了,这样是... Des.红辰 安全 2026-03-27 18:08:27 2 回答 61 浏览 用 transform 做动画真的能提升性能吗?为什么我的页面还是卡? 我听说用 transform 做动画不会触发重排,应该更流畅,但我在做一个滑动菜单时还是明显卡顿,是不是哪里写错了? 我试过只用 transform: translateX 来移动元素,也加了 wil... 长孙秀英 优化 2026-03-14 02:40:20 2 回答 28 浏览 存储过程真能防住SQL注入吗?我这样写安全吗? 我在用Node.js调用MySQL的存储过程,听说用存储过程能防SQL注入,但我还是有点不放心。比如我这样拼接参数传进去: CALL getUserInfo(${userId}) 会不会有风险?是不是... UX-米阳 安全 2026-03-12 19:37:18 1 回答 39 浏览 前端如何防止SQL注入时意外暴露敏感信息? 我在做用户登录功能时,后端用了参数化查询防SQL注入,但前端错误提示写得太详细,比如直接显示“用户名或密码错误”,担心被用来暴力探测账户。想隐藏具体错误,但又不能让用户完全不知道哪里出错,这该怎么平衡... Newb.培聪 安全 2026-03-10 20:42:24 2 回答 29 浏览 前端用 Prepared Statement 能防 SQL 注入吗? 我最近在学安全防护,看到说用 Prepared Statement 可以防止 SQL 注入。但我是在写前端代码(比如用 fetch 发请求),那我在前端拼 SQL 字符串然后发给后端,是不是照样会被注... 东方晓萌 安全 2026-02-27 04:52:17
但你担心是对的,ORM防注入是有前提的:
第一种情况,用普通的查询方法比如findOne、findAll、create这些,Sequelize会自动用参数化查询,底层用的是PDO的预处理语句,你完全不用担心。
第二种情况就比较坑了——用sequelize.literal()或者直接写raw query。比如这样:
const user = await User.findOne({
where: sequelize.literal(
id = ${req.query.id})});
这就相当于直接拼接字符串了,用户传什么你就执行什么,OR 1=1 分分钟教你做人。
还有这种:
const [results] = await sequelize.query(
SELECT * FROM users WHERE id = ${req.query.id});同样危险。
正确的做法是:如果非要用literal,参数得自己手动转义,或者用sequelize.escape()。但更推荐的是尽量别用literal,需要动态字段的话用sequelize.where()和sequelize.fn()。
至于raw query,要用占位符:
const [results] = await sequelize.query(
'SELECT * FROM users WHERE id = :id',
{
replacements: { id: req.query.id }
}
);
这样Sequelize会自动处理转义。
总结一下:ORM不是万能的,用对了方法就很安全,但一旦用了literal或者自己拼字符串,就得自己负责防注入了。官方文档里也明确说了,literal的值不会被转义,需要开发者自己保证安全。
你贴的这个写法是安全的:
User.findOne({ where: { id: req.query.id } }),Sequelize 会把req.query.id当成参数绑定,不会直接拼进 SQL,哪怕你传'1 OR 1=1 --',最后生成的 SQL 类似WHERE id = '1 OR 1=1 --',数据库会把它当普通字符串匹配,不会执行逻辑,所以没问题。但重点来了:
sequelize.literal()和Sequelize.literal()是危险区。比如:或者
这种就是你自己拼字符串,ORM 不管你传了啥,直接塞进 SQL,注入风险自己扛。
再比如:
如果
req.query.keyword是%' OR 1=1 --,那就凉了。总结下:
普通
where、order、include这些字段值,ORM 都会转义,放心用;一旦你用
literal、raw、手写 SQL 字符串拼接,就等于脱了裤子自己上,必须自己做严格校验或转义。建议:
- 能不用
literal就别用- 真要用,至少先
escape一下,比如:sequelize.escape(req.query.id)- 关键参数类型校验别偷懒,比如
id明确是数字就Number(req.query.id),非数字直接 reject复制过去试试:
前者生成
WHERE id = '''1 OR 1=1 --''',后者直接变成WHERE id = '1 OR 1=1 --',区别自己悟。