在Sequelize中使用findOrCreate时如何防止SQL注入?
最近在用Sequelize做用户注册功能时,发现直接拼接查询条件可能会有SQL注入风险。比如这样写:
User.findOrCreate({
where: {
username: req.body.username
},
defaults: {
password: req.body.password
}
})
但查文档后看到应该用参数化查询,可我这样改之后总报错:
User.findOrCreate({
where: sequelize.literal("username = ?"),
replacements: [req.body.username],
defaults: {...}
})
错误提示说找不到正确的参数绑定方式。那正确的findOrCreate参数化写法应该是什么样的?直接用req.body传参到底安不安全?
先说结论:你原代码里直接用
req.body.username是安全的,Sequelize 的findOrCreate默认就会做参数化处理,根本不用你手动写sequelize.literal那一套。问题出在你改写的那一版——
where: sequelize.literal("username = ?")这种写法根本不对。Sequelize 的findOrCreate里where字段支持的对象写法本身就是参数化的,你一用literal反而绕过了它的安全机制,还搞乱了参数绑定逻辑。正确的写法就两行:
where: { username: req.body.username }defaults: { password: req.body.password }就这么简单,Sequelize 会自动把
req.body.username当作参数传进去,生成类似WHERE username = ?的语句,底层用的是mysql或pg的预处理语句,完全防注入。你要是真想用
literal(比如要写复杂表达式),得配合replacements一起用,但必须注意:replacements是整个查询语句级别的,不是findOrCreate的顶层字段。比如:但这种情况极少用,除非你要写
OR、LIKE、DATE()这种 Sequelize 对象写法表达不了的逻辑。再强调一遍:你原来那版代码是安全的,别自己加戏。只要别手滑拼接字符串(比如
where: { username: 'xxx' + req.body.username }),Sequelize 就能护你周全。顺带一提:密码记得用
bcrypt加密存,别直接存明文,这个比 SQL 注入更容易翻车。自动防注入,别乱改就行。where: { username: req.body.username }