客户端校验仅提升用户体验,不能替代后端参数化查询和最小权限数据库配置;必须前后端白名单规则一致,所有输入经后端二次校验,禁用字符串拼接SQL。

客户端校验只是障眼法,不能替代后端过滤
前端做 SQL 注入防护,本质是防手误、防低级爬虫,不是防攻击者。只要禁用 JS 或绕过表单提交(比如用 curl 直发请求),所有前端校验都形同虚设。它唯一靠谱的用途,是提升用户体验——让用户输完立刻知道“这个字段不能填单引号”,而不是等几秒后收个 500 错误。
常见错误现象:onsubmit 里写正则过滤 '、;、--,结果用户贴一段带中文全角符号的恶意 payload 就穿过去了;或者只校验输入框,却忘了 select、hidden 字段也能被篡改。
- 校验必须覆盖所有可提交字段,包括
input[type=hidden]、textarea、select和动态生成的字段 - 正则别只盯着 ASCII 特殊字符,
String.fromCharCode(8217)(右单引号)这类 Unicode 变体也要处理 - 不要用黑名单思路(如“禁止
SELECT”),容易漏;优先用白名单(如“只允许字母数字和下划线”)
JavaScript 中最实用的客户端过滤写法
真正能落地的校验,不是拦截所有可疑字符,而是对字段做语义化约束。比如邮箱字段就该走 email 类型 + HTML5 pattern + JS test() 三重确认;搜索关键词可以允许单引号,但必须转义为两个单引号('')再传给后端——前提是后端明确按这个规则解析。
示例:对用户名字段做安全预处理(非拦截,是规整):
function sanitizeUsername(str) {
return str
.replace(/'/g, "''") // SQL Server 风格转义,供后端参考
.replace(/[^\w\u4e00-\u9fa5\-]/g, '') // 只留字母、数字、中文、下划线、短横线
.slice(0, 32); // 长度截断,防超长 payload
}
- 避免在客户端做
escape或encodeURI,这些对 SQL 解析毫无意义 - 别调用
eval、Function构造器拼接字符串,这等于主动开后门 - 如果用框架(如 React/Vue),确保校验逻辑在
onChange和onSubmit两处都触发,不依赖 DOM 快照
前后端校验不一致时,后端永远以自己为准
前端提示“用户名不能含特殊字符”,后端却接受 @ 和点号——这种不一致会导致两种后果:一是用户困惑(明明按提示填了还报错),二是攻击者发现前端宽松、后端严格,转而专攻后端没覆盖的边界路径(比如 API 直连、旧版接口、批量导入 CSV)。
关键参数差异:max_length、allowed_chars、trim_behavior(是否自动去首尾空格)、null_handling(空字符串算合法还是拒绝)——这些必须前后端配置完全同步,最好从同一份 JSON Schema 生成校验规则。
- 后端收到数据后,第一件事不是查库,而是重新跑一遍和前端一模一样的白名单正则(哪怕多一次
RegExp.test()) - 如果后端用了 ORM(如
Sequelize、SQLAlchemy),确认它没被手动拼接进raw query;where条件一律走参数化绑定,不用+拼字符串 - 日志里记录被拒绝的原始请求体(脱敏后),方便比对前后端规则偏差
真正防住 SQL 注入,靠的是后端参数化查询 + 最小权限 DB 账户
客户端校验再细,也挡不住直接连数据库的工具(如 mysql -h xxx -u root -p)。唯一可靠防线只有两条:所有查询必须用参数占位符(? 或 $1),数据库账户仅授予必要表的 SELECT/INSERT 权限,禁用 LOAD_FILE、INTO OUTFILE 等高危命令。
性能影响几乎为零,但兼容性要注意:MySQL 的 PREPARE 语句不支持动态表名或列名,这类需求必须靠白名单映射(比如前端传 sort=created_at,后端查表确认它属于 ['id', 'created_at', 'status'] 才放行)。
- Node.js 用
pg时,坚持用client.query('SELECT * FROM users WHERE id = $1', [id]),绝不用client.query('SELECT * FROM users WHERE id = ' + id) - PHP 用
PDO时,prepare()后必须execute(),且绑定值用bindParam()或数组传参,不用字符串插值 - Java 的
PreparedStatement要注意setString()对 null 的处理,别因空指针跳过校验
最容易被忽略的是存储过程调用和动态 SQL 拼接场景——哪怕只拼接字段名,也得走白名单校验,不能因为“看起来不危险”就放开。










