前端js校验拦不住真实请求,因其运行在用户可控环境,禁用js、删事件监听器或直接调用submit()、fetch()均可绕过;php服务端必须独立重做全部校验逻辑,不信任任何$_post/$_get数据。

前端JS校验为什么拦不住真实请求
因为所有 JS 校验逻辑都运行在用户可控环境中,只要禁用 JS、改 DOM、删事件监听器或直接调用 form.submit(),就能完全绕过。浏览器不会阻止你手动构造一个 fetch() 请求发给后端——此时前端校验函数压根没执行。
常见绕过方式包括:
- 在开发者工具中禁用 JavaScript 后填写非法值(如邮箱填
"<script>alert(1)</script>@test.com")并提交 - 右键“检查”→ 删除
input上的oninput或onsubmit属性 - 用
curl或 Postman 手动发 POST 请求,字段值任意设(比如把price=999改成price=-1) - 用 Burp Suite 拦截请求后修改参数,再转发——连页面都不用打开
PHP服务端验证必须重做全部规则
不能复用前端 JS 的正则、长度判断或空值检查逻辑,必须在 PHP 中独立实现相同甚至更严的校验。例如:
- 前端用
/^1[3-9]\d{9}$/校验手机号 → PHP 必须用filter_var($phone, FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => '/^1[3-9]\d{9}$/']])或更严格的号段白名单 - 前端只 trim() 一次 → PHP 要用
trim($str, " \t\n\r\0\x0B\xC2\xA0")清除全角空格和 Unicode 零宽字符 - 前端检查
password === confirmPassword→ PHP 必须分别取$_POST['password']和$_POST['confirm_password']再比对,不能假设前端没改 hidden 字段
关键点:PHP 不应信任任何来自 $_POST 或 $_GET 的值,包括 type="hidden" 字段、disabled 控件的 value、甚至 data- 属性里塞的“校验通过”标志。
使用 JSON Schema 验证 JSON 数据,从示例 JSON 生成 schema,并将其转换为 TypeScript 接口、Python 数据类或 Markdown 文档。
最容易被忽略的 PHP 验证盲区
很多 PHP 开发者只做基础过滤,却漏掉三类高危场景:
-
类型混淆:前端传字符串
"123",PHP 用==判断时可能被转为 int,导致"123abc" == 123成立;必须用===或显式is_int()/is_string() -
隐藏字段篡改:如
<input type="hidden" name="role" value="user">,攻击者可改为admin;PHP 必须忽略该字段,从 session 或 JWT 中读取真实角色 -
业务状态依赖校验:比如“只有订单状态为 pending 才能取消”,前端 JS 可能根据按钮是否 disabled 来判断,但 PHP 必须查数据库确认当前状态,不能信表单里的
status值
PHP 验证失败后必须中断写入流程
这是最常出问题的一环:错误提示打了,但数据库插入语句仍在执行。根本原因是验证逻辑和写入逻辑没有强耦合。
正确做法是用单一 $valid 标志控制后续流程:
$valid = true;
if (empty($_POST['email'])) {
$errors[] = '邮箱不能为空';
$valid = false;
}
if (!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
$errors[] = '邮箱格式不合法';
$valid = false;
}
// ……其他校验
if ($valid) {
// ✅ 只有这里才执行 INSERT / UPDATE
$stmt = $pdo->prepare("INSERT INTO users (email) VALUES (?)");
$stmt->execute([$_POST['email']]);
} else {
// ❌ 错误数组返回给前端,不写库
echo json_encode(['success' => false, 'errors' => $errors]);
}
注意:不要在验证块里用 return 或 exit,那会让代码难以测试和扩展;用标志位更清晰、可维护。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










