LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

为什么永远不要相信前端输入?绕过前端验证,只需一个 cURL 命令!

zhenglin
2026年1月4日 9:20 本文热度 466

上个月 Code Review,我拦下了一个新人的代码。

他写了一个转账功能,前端做了极其严密的校验:


  • 金额必须是数字。

  • 金额必须大于 0。

  • 余额不足时,提交按钮是 disabled 的。

  • 甚至还写了复杂的正则表达式,防止输入负号。


他自信满满地跟我说:老大,放心吧,我前端卡得死死的,用户绝对传不了非法数据。

我笑了笑🤣,没看他的后端代码,直接打开终端,敲了一行命令。

0.5 秒后,他的数据库里多了一笔“-10000”的转账记录,余额瞬间暴涨!

他看着屏幕,目瞪口呆:这……你是怎么做到的?我按钮明明置灰了啊!


今天,我就来揭秘这个所有后端(和全栈)工程师必须铭记的第一铁律:

前端验证,在黑客眼里,只是个小case🤔。




验证:

假设我们有一个购物网站,前端有一个简单的购买表单。

前端逻辑(看似完美):

// Front-end code

function submitOrder(price, quantity) {

  // 1. 校验价格不能被篡改

  if (price !== 999) {

    alert("价格异常!");

    return;

  }

  // 2. 校验数量必须为正数

  if (quantity <= 0) {

    alert("数量必须大于0!");

    return;

  }

  

  // 发送请求

  api.post('/buy', { price, quantity });

}

你看,用户在浏览器里确实没法作恶。他改不了价格,也填不了负数。

但是黑客,从来不用浏览器点你的按钮。

第一步:打开DevTools Network 面板,正常点一次购买按钮。捕获到了这个请求。

第二步:请求上右键 -> 复制 -> cURL 格式复制。

 

这一步,我已经拿到了你发送请求的所有密钥:URL、Headers、Cookies、以及那个看似合法的 Data。


第三步
:打开终端(Terminal),粘贴刚才复制的命令。但是,我并没有直接回车。


我修改了 --data-raw 里的参数:

  • "price": 999 改成了 "price": 0.01

  • 或者把 "quantity": 1 改成了 "quantity": -100


# 经过魔改后的命令

curl 'http://localhost:3000/user/buy' \

  -H 'Cookie: session_id=...' \

  -H 'Content-Type: application/json' \

  --data-raw '{"price": 0.01, "quantity": 10}' \

  --compressed

回车!

服务器返回:{ "status": "success", "msg": ok!" }

恭喜你,你的前端验证毫发无损,但你的数据库已经被我击穿了。 我用 1 分钱买了 10 个商品,或者通过负数数量,反向刷了库存。



为什么前端验证, 防不了小人🤔

很多新人最大的误区,就是认为用户只能通过我的 UI 来访问我的服务器。

错!大错特错!

Web 的本质是 HTTP 协议。

HTTP 协议是无状态的、公开的。任何能够发送 HTTP 请求的客户端,都是你的用户。

  • Chrome 是客户端。

  • cURL 是客户端。

  • Postman 是客户端。

  • Python 的 requests 脚本也是客户端。

  • node 的 http 脚本也是客户端

前端代码运行在用户的电脑上。


这意味着,用户拥有对前端代码的绝对控制权

  • 他可以禁用 JS。

  • 他可以在 Console 里重写你的校验函数。

  • 他可以拦截请求(用 Charles/Fiddler)并修改数据。

  • 他甚至可以完全抛弃浏览器,直接用脚本轰炸你的 API。

所以,前端验证的唯一作用,是提升用户体验 (比如提示用户格式不对😂),而不是提供安全性😖。



后端该如何防御?(不要裸奔)

既然前端不可信,后端(或 BFF 层)就必须假设所有发过来的数据都是有毒的

1. 永远不要相信 Payload 里的关键数据

前端只传 productId。后端拿到 ID 后,去数据库里查这个商品到底多少钱。永远以数据库为准。


2. 使用 Schema 校验库(Zod / Joi / class-validator)

不要在 Controller 里写一堆 if (req.body.age < 0)。

使用专业的 Schema 校验库,定义好数据的规则。

TypeScript代码👇:

// 使用 Zod 定义后端校验规则

const OrderSchema = z.object({

  productId: z.string(),

  // 强制要求 quantity 必须是正整数,拦截 -100 这种攻击

  quantity: z.number().int().positive(), 

  // 注意:这里根本不接收 price 字段,防止被注入

});


// 如果校验失败,直接抛出 400 错误,逻辑根本进不去

const data = OrderSchema.parse(req.body); 

3. 权限与状态校验

不要只看数据格式对不对,还要看人对不对。

  • 这个用户有权限买这个商品吗?

  • 这个订单现在的状态允许支付吗?(防止重复支付攻击🤔)



还有一种更高级的攻击:Replay Attack(重放攻击)

你以为校验了数据就安全了?

如果我拦截了你一次领优惠券的请求,虽然我改不了数据,但我可以用 cURL 连续运行 1000 次这个命令。

for i in {1..1000}; do curl ... ; done


如果你的后端没有做幂等性(Idempotency)校验或频率限制(Rate Limiting) ,那我瞬间就能领走 1000 张优惠券。

防御手段👇:

Redis 计数器:限制每个 IP/用户 每秒只能请求几次。

唯一 Request ID:对于关键操作,要求前端生成一个 UUID,后端处理完后记录下来。如果同一个 UUID 再次请求,直接拒绝。




对于前端安全,所有的输入都是可疑的🤔

作为全栈或后端开发者,当你写 API 时,请忘掉你那个漂亮的前端界面。

你的脑海里应该只有一幅画面:


屏幕对面,不是一个点鼠标的用户,而是一个正在敲 cURL 命令的黑客。

只有这样,你的代码才算真正安全了😒。


参考文章:原文链接


该文章在 2026/1/4 9:21:39 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2026 ClickSun All Rights Reserved