vue 3 前端不防 sql 注入,只做输入长度限制、类型校验等快速失败;真正防御靠 express 后端 100% 参数化查询(?/$1/命名参数)、结构部分白名单校验,并覆盖 query/params/headers 所有入口。

Vue 3 前端本身不能防止 SQL 注入,也完全不参与数据库查询执行;真正能卡住 SQL 注入的,只有 Express 后端中那一个 ? 占位符、或 ORM 的参数绑定机制。前端唯一该做的事,是让非法输入在抵达后端前就“快速失败”,而不是假装自己在防注入。
前端 Vue 3 只做快速失败,不做安全拦截
用户在表单里输 ' OR 1=1 --,Vue 层不该试图用正则去“过滤”它——这种 payload 本就符合邮箱/用户名格式,正则拦不住,且攻击者绕过 JS 只需一条 curl 就行。
- 限制输入长度:比如搜索关键词
searchTerm超过 200 字符直接throw new Error('输入过长'),避免后端处理无意义大 payload - 类型强校验:ID 字段用
Number.isInteger(Number(id))判断,非数字立即报错,不传给后端 - 不自动 trim 或强转:
v-model.trim会吃掉首尾空格,但某些业务需要保留(如用户名开头空格),且 trim 不影响注入;保持原始值交付,由后端决定是否清洗 - 所有校验逻辑必须与后端一致:如果后端要求邮箱长度 ≤ 100,前端也得用同一上限,否则出现“前端能提交、后端 400 拒收”的体验断层
Express 后端必须 100% 使用参数化查询
只要出现字符串拼接,无论多“简单”,都等于开门揖盗。比如 WHERE name = '${req.body.name}' 或 ORDER BY ${req.query.sort},都是高危写法。
- MySQL 场景:用
mysql2,query()必须传数组参数:pool.execute('SELECT * FROM users WHERE id = ?', [req.query.id]) - PostgreSQL 场景:用
pg,必须用$1形式:client.query('SELECT * FROM logs WHERE level = $1', ['error']),不能混用? - SQL Server 场景:用
mssql,优先用命名参数:request.input('username', sql.NVarChar(50)).query('SELECT * FROM users WHERE username = @username') - ORM 用户(Sequelize / TypeORM):只用模型方法,如
User.findOne({ where: { email: req.body.email } });严禁在 ORM 中调用sequelize.query("..."+userInput)
表名、字段名、ORDER BY 等结构部分必须白名单硬编码
? 和 $1 只能用于值,不能用于 SQL 结构。动态表名或排序字段若来自用户输入,必须走白名单校验。
- 定义允许的表名列表:
const ALLOWED_TABLES = ['users', 'posts', 'comments'] - 校验逻辑要前置:
if (!ALLOWED_TABLES.includes(req.query.table)) throw new Error('Invalid table') - 排序字段同理:
const ALLOWED_SORT_FIELDS = { users: ['name', 'created_at'], posts: ['title', 'published_at'] },再按表名查白名单 - 别信“转义后就能拼接”——
mysql.escapeId()或pg.format()是辅助工具,不是银弹;白名单才是唯一可靠手段
容易被忽略的注入入口:query、params、headers 全都要过参数化
很多开发者只盯着 req.body,却忘了 URL 查询参数、路径参数、甚至请求头里的 X-Forwarded-For 或 Sort-By 都可能进 SQL。
-
GET /api/users?id=1→req.query.id必须进?占位 -
GET /api/posts/:category→req.params.category若用于WHERE category = ?,同样要参数化 - 自定义请求头如
X-User-ID若用于审计日志的INSERT,也得走参数化,不能拼进 SQL 字符串 - 错误日志里别直接打印原始 SQL:
console.error('Query failed:', query)可能泄露拼接逻辑;应记录参数化后的模板 + 参数摘要
最难的不是写对某一行 query(),而是确保所有分支路径——包括 if/else 分支、分页逻辑、导出 CSV 的 SQL、甚至中间件里偷偷拼的统计语句——全都统一走参数化。漏一处,整套防线就失效。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











