SQL 注入长期位居 OWASP Top 10 榜单前列,而 Node.js 作为高并发后端的热门选择,其与 MySQL 的交互安全性直接关系到整个应用的数据底线。很多开发者以为用了 ORM 就万事大吉,或者觉得参数化查询“太麻烦”,结果在生产环境埋下致命隐患。本文从攻击原理出发,结合 Node.js 生态的实际代码,系统梳理防止 SQL 注入的几种可靠方案。
SQL 注入为什么在 Node.js 中同样危险
SQL 注入的本质是用户输入被当作 SQL 代码执行。在 Node.js 中,常见的高危写法是字符串拼接:
const sql = `SELECT * FROM users WHERE name = '${req.query.name}'`;
connection.query(sql, (err, results) => { ... });
当攻击者传入 ' OR '1'='1 时,查询条件恒真,可绕过登录验证;传入 '; DROP TABLE users; -- 则可能直接删表。Node.js 的异步特性并不会降低这种风险,反而因为回调嵌套容易让开发者忽略输入来源的校验。
方案一:使用参数化查询(预处理语句)
这是最推荐、最有效的方式。MySQL 驱动 mysql 和 mysql2 都支持占位符 ?,驱动会将参数与 SQL 模板分开传输,数据库先编译 SQL 结构,再填入数据,从根本上杜绝注入。
const sql = 'SELECT * FROM users WHERE name = ? AND password = ?';
connection.query(sql, [req.body.name, req.body.password], (err, results) => {
// 即使传入 ' OR '1'='1,也只会被当作普通字符串匹配
});
使用 mysql2/promise 版本时写法更清晰:
const [rows] = await connection.execute(
'SELECT * FROM users WHERE id = ?',
[userId]
);
注意:表名、列名、ORDER BY 字段不能用 ? 占位,这些属于 SQL 结构部分。如果确实需要动态排序,必须用白名单校验:
const allowedColumns = ['id', 'name', 'created_at'];
const orderBy = allowedColumns.includes(req.query.sort)
? req.query.sort
: 'id';
const sql = `SELECT * FROM users ORDER BY ${orderBy} DESC`;
方案二:使用 ORM 或 Query Builder
Sequelize、TypeORM、Knex.js 等工具默认使用参数化查询,能大幅减少手写 SQL 的风险。
// Sequelize
await User.findOne({ where: { name: req.body.name } });
// Knex
await knex('users').where('name', req.body.name).first();
但要注意:ORM 的 raw 方法或 whereRaw 如果拼接了用户输入,同样会引入注入。例如 knex.raw(\SELECT * FROM users WHERE name = '${name}'`)` 就是典型的错误用法。
方案三:输入校验与最小权限原则
参数化查询是核心防线,但纵深防御同样重要:
- 输入校验:对邮箱、手机号、ID 等字段用
validator或joi做格式校验,拒绝不符合预期的输入。 - 最小权限:连接 MySQL 的账号只授予必要权限。应用账号不应拥有
DROP、FILE、GRANT等权限,即使被注入,损失也可控。 - 错误信息脱敏:不要把数据库原始错误直接返回给前端,避免泄露表结构。
- 转义函数:
mysql.escape()可作为兜底,但不应作为主要手段,因为它容易遗漏。
关联安全话题速览
XSS 的常见方式和前端如何防御
XSS 与 SQL 注入常在同一应用中并存。常见方式包括反射型(恶意链接)、存储型(评论注入)和 DOM 型(前端脚本拼接)。前端防御要点:对用户内容输出时使用 textContent 而非 innerHTML;使用 DOMPurify 等库净化富文本;设置 Content-Security-Policy 响应头限制脚本来源;Cookie 加 HttpOnly 防止脚本读取。
MySQL 防止 SQL 注入的几种写法
在数据库层面,除了应用层参数化,还可以:使用存储过程并配合参数绑定;对数据库账号做权限隔离;开启 sql_mode 严格模式减少隐式转换;审计慢查询日志发现异常 SQL。但核心仍是应用层不拼接用户输入。
Linux 服务器安全加固清单
数据库安全离不开主机安全:及时更新系统补丁;禁用 root 远程登录,改用密钥认证;配置防火墙仅开放必要端口(如 3306 不对外网开放);使用 fail2ban 防暴力破解;定期审计 authorized_keys 和定时任务;对数据库备份文件加密存储。
总结
Node.js 连接 MySQL 防注入,记住三条铁律:永远用参数化查询,永远不拼接用户输入,永远给数据库账号最小权限。ORM 和 Query Builder 能降低出错概率,但不能替代安全意识。把参数化查询作为默认习惯,再配合输入校验和权限隔离,才能让应用在真实攻击面前站得住脚。
未经允许不得转载:任鹏个人博客 » Node.js 连接 MySQL 时如何防止 SQL 注入


朋友圈点赞图在线生成源码