node.js层必须用参数化查询(如?占位符+数组传参),前端vue校验对sql注入零防护力;mysql.escape()不可靠,因宽字节可绕过且返回带引号字符串,仍致注入。

Node.js 层必须用参数化查询,前端 Vue 校验对 SQL 注入零防护力——这是唯一需要记住的前提。
为什么 mysql.escape() 不可靠
它只适配 MySQL,且宽字节编码(如 %df%27)可绕过;更关键的是,escape() 返回的是带引号的字符串,比如 'admin'' OR 1=1 -- ',拼进 SQL 后变成 WHERE name = 'admin'' OR 1=1 -- ',仍能执行注入。这不是“加固”,是假安全。
- 真正安全的路径只有一条:用
?占位符 + 数组传参,例如pool.execute('SELECT * FROM users WHERE email = ?', [req.body.email]) - 所有用户输入入口都得走这条路:不只是
req.body,还有req.query.id、req.params.slug、甚至req.headers['x-tenant-id'] - ORM 如 Sequelize 默认走参数化,但一旦调用
sequelize.query()并拼接字符串,立刻失效
ORDER BY 字段和表名为什么不能用 ?
因为 ? 只能替换成值(value),不能替换成结构(structure)。数据库预编译时,ORDER BY ? 会被当成排序一个字段名为“?”的列,不是你传进去的字符串。
使用 `@ainative/vue-sdk` 为 Vue 3 应用添加 AI 聊天功能。适用于以下场景:(1) 安装 `@ainative/vue-sdk`,(2) 在 Vue 组件中使用 `useChat` 组合式函数,(3) 提供……
- 动态表名/列名/排序字段必须硬编码白名单,例如:
const allowedSorts = { createdAt: 'created_at', name: 'name' };,再取allowedSorts[req.query.sort] || 'id' - 错误做法:
SELECT * FROM ${req.query.table} WHERE id = ?—— 白名单校验必须在拼接前完成,且不允许 fallback 到默认值以外的任意字符串 - 别信正则过滤单引号或分号,
`、%27、0x27都能绕过
Vue 层该做什么,不该做什么
Vue 的作用不是防注入,而是让后端的参数化查询不被意外破坏。
- 搜索字段保持原始字符串传参,不要
.trim()后再手动加引号——那是后端 ORM 或 query 构建器该干的事 - 路由参数如
/user/:id建议显式转成字符串:router.push({ name: 'User', params: { id: String(rawId) } }),避免大整数被 Vue Router 自动转 number 导致精度丢失 - 避免在 axios 请求里做类型强转:
params: { id: Number(id) }可能让NaN传成字符串"NaN",后端再parseInt仍是NaN,最终拼出WHERE id = NaN
最常被忽略的点是:表名、排序字段、多租户 header、分页 offset/limit —— 这些只要进了 SQL 字符串拼接环节,就等于把门钥匙交给了攻击者。参数化不是“用了 ORM 就万事大吉”,而是每一行 query、execute、$queryRaw 都要亲手确认:用户输入是否只出现在 ? 对应的数组里,还是悄悄混进了 SQL 模板中。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










