BLOG
前端表单校验不能替代后端校验
前端校验负责即时反馈,后端校验负责真正的数据安全。
用户在浏览器里填完表单,点下提交,前端脚本立刻标出“邮箱格式不对”“密码太短”——体验很顺。但这份顺滑只发生在浏览器这一侧。请求一旦离开页面,直接打到服务器接口,前端做的所有检查都不再存在。绕过浏览器提交请求太容易了,打开开发者工具、写一段脚本、甚至用命令行工具就能做到。后端校验才是数据进入系统前的最后一道闸门,前端校验只是让正常用户少走弯路。
前端校验管什么,后端校验管什么
前端校验的价值在于即时反馈。用户不用等一个完整的网络往返,才知道自己漏填了必填项或选错了格式。这种交互上的顺畅能显著减少无效提交,也减轻服务器压力。常见的做法是用HTML自带的类型和约束属性,比如required、type="email"、maxlength,浏览器会基于这些声明直接阻止提交并显示提示。
```html
<form id="signup">
<label for="email">邮箱</label>
<input type="email" id="email" name="email" required>
<button type="submit">注册</button>
</form>
```
这段代码在桌面浏览器上工作良好,但换到某些老旧浏览器或关闭了JavaScript的环境里,约束验证可能不触发,表单会直接提交。更关键的是,请求本身不依赖页面上的任何检查——攻击者完全可以构造一个不带email字段的POST请求发给服务器。所以前端校验的定位始终是“提升体验”,而不是“保障安全”。
后端校验才是数据正确性的最终裁决者。它需要重新检查长度、类型、格式、取值范围,还要确认权限——这个用户有没有资格提交这份数据、能不能修改这条记录。后端校验不能假设请求来自你的页面,不能假设字段齐全,不能假设值合法。每一条进入系统的数据,都要当作不可信输入来处理。
判断校验是否到位的三个问题
拿到一个表单需求,先别急着写代码。问自己三个问题:这个数据会被谁提交?提交后流经哪些环节?如果数据非法,会造成什么后果?
第一个问题决定校验的严格程度。公开的注册页面面对的是所有人,垃圾注册和批量提交是常态;后台管理员的表单面对的是少数受信用户,但权限越界和参数篡改的风险反而更高。第二个问题决定校验放在哪里。数据可能经过前端页面、API网关、应用服务、数据库多个节点,每一层都有各自的职责。第三个问题决定校验失败的代价。一条留言格式不对,顶多显示乱码;一笔订单金额被篡改,损失就是实际的。
判断标准很简单:如果绕过前端页面,直接向服务器发送请求,数据是否仍然安全?如果答案是“不一定”,那后端校验就有缺口。
容易出错的位置
命名和结构不统一是第一类高频问题。前端字段叫userName,后端字段叫username,数据库列叫user_name,映射关系散落在各处,校验逻辑写到一半就分不清谁是谁。更隐蔽的是同名字段在不同接口里含义不同——一个接口的status表示审核状态,另一个接口的status表示启用状态,校验规则自然也不同。
第二类问题是只测成功路径。填好所有字段、点击提交、看到成功提示,这条链路跑通了就以为完事了。空数据、超长文本、特殊字符、重复提交、并发请求,这些边界情况才是校验逻辑真正接受考验的地方。一个只检查“是否为空”的接口,收到一个由一万个字符组成的“名字”时,可能直接撑爆数据库字段长度。
第三类问题是为了体验牺牲安全。有些团队为了让用户少填东西,把必填项改成选填,或者在前端把校验规则写得很宽松,后端也跟着放松。反过来,也有团队把前端校验做得极其复杂——密码必须包含大小写字母、数字、特殊字符中的三种且不少于十位——用户被折腾得够呛,但攻击者根本不在乎这些规则,他们直接构造请求。
边界情况:加载失败、窄屏与键盘操作
校验逻辑还需要考虑页面本身不可用的情况。假设用户网络不稳定,表单页面的JavaScript文件加载失败,此时HTML内置的约束验证可能还在,但自定义的校验逻辑和错误提示全部失效。表单会直接提交到服务器,如果后端没有兜底校验,非法数据就进去了。
窄屏设备上,错误提示的展示方式也需要留意。桌面端常见的做法是在输入框右侧显示红色小字,但手机屏幕宽度有限,提示文字可能被截断或换行后遮挡相邻元素。更稳妥的做法是把错误信息放在输入框下方,并确保它不依赖hover等鼠标操作才能看到。
键盘用户走的是另一条路径。用Tab键逐个切换焦点时,错误提示需要能被屏幕阅读器感知,比如用aria-describedby把输入框和错误信息关联起来。如果校验失败后焦点没有移回出错的输入框,键盘用户会迷失在页面里,不知道发生了什么。
如何验证校验是否真的可靠
验证不能只靠浏览器里点一遍。打开开发者工具的Network面板,找到表单提交的请求,右键选择“Edit and Resend”,删掉几个字段再发送——服务器是否拒绝了?把邮箱字段改成一段乱码再发送——服务器是否识别出来了?这是最直接的测试方式,模拟的就是绕过前端的行为。
权限校验的验证方式类似。用一个普通用户身份登录,手动修改请求中的资源ID或用户ID,看看能否访问或修改不属于自己的数据。如果服务器只检查了“是否登录”而没有检查“是否有权操作”,这种越权漏洞在功能测试里很难发现,但危害极大。
另一项验证是重复提交。快速点击提交按钮两次,或者用脚本连续发送相同请求,后端是否做了幂等处理?没有防重机制的接口,在用户网络延迟时可能出现一条留言提交两次、一笔订单创建两遍的情况。
完成后留一段简短记录:改了什么、为什么改、检查过哪些边界、如何恢复。这些信息不占多少空间,半年后接手的人——很可能就是你自己——会感谢这段记录。前端校验让表单好用,后端校验让数据可靠,两者各司其职,缺一不可。
评论
登录后可发表评论。