拿到一个网站API源码,网站第一件事不是网站看它支持多少接口,而是网站翻到鉴权那一段。我见过太多项目,网站接口列表写得漂漂亮亮,网站文档也齐全,网站结果token校验逻辑里藏着硬编码的网站密钥。这种东西一旦进了公开仓库,网站等于把大门钥匙插在锁上。网站
去年帮朋友排查一个漏洞,网站他的网站电商站点API源码被拖下来了。问题出在一个看似不起眼的网站文件——
api/v1/user_info.php。代码里直接写了$uid = $_GET['uid'];,网站然后拿这个uid去数据库查订单。网站没有session校验,网站没有签名比对。攻击者写个循环,从1跑到10000,就能把全站用户的手机号和收货地址全捞出来。这种写法在早期PHP项目里特别常见,开发者觉得“反正前端会传对”,但前端能改,抓包工具一拦,参数随便换。API源码的结构其实比很多人想的要简单。一个入口文件,通常叫
index.php或者api.php,负责路由分发。然后按模块拆成控制器,比如UserController、OrderController。每个控制器里再分方法,对应不同的接口路径。麻烦的地方在于,很多人把业务逻辑直接塞进控制器,一个方法写三百行,数据库查询、参数过滤、返回格式化全混在一起。这种代码能跑,但改起来要命。我更喜欢看到的是三层:路由层只做参数接收和校验,服务层处理业务,数据层只管读写。哪怕是小项目,这么拆也不费事。参数校验是API源码里最容易被忽略的部分。有人觉得前端已经用JS校验过了,后端不用重复。这想法很危险。前端校验是给正常用户看的,后端校验才是给攻击者准备的。比如一个转账接口,前端限制金额不能为负,但攻击者直接发请求,把
amount改成-100,如果没有后端校验,余额反而会增加。正确的做法是在源码里写死规则:金额必须是正数,且不能超过账户余额。这些判断要放在数据库操作之前。返回格式也值得说两句。有些源码里每个接口的返回结构都不一样,有的用
code: 0表示成功,有的用code: 200,还有的用success: true。前端对接的时候得写一堆if-else。我习惯在源码里定义一个统一的响应类,比如ApiResponse::success($data)和ApiResponse::error($msg, $code)。所有接口都走这个出口,前端只需要判断一个字段。这不算什么高深设计,但能省掉很多沟通成本。日志记录是另一个分水岭。差的API源码出错了只返回一个
false,好的源码会把请求参数、用户ID、时间戳、错误堆栈全写进日志文件。有一次调试一个支付回调接口,对方一直说没收到通知。我翻了源码里的日志,发现回调地址被写死成了测试环境的域名。这种问题,没有日志就得靠猜。最后说一个细节:API源码里的注释。我见过最离谱的一个文件,开头写着
// 此接口已废弃,请勿使用,但路由里还挂着,而且没有返回410状态码。新来的开发者照着旧文档调了半天,浪费时间。废弃的接口要么直接删掉,要么在源码里返回明确的错误提示。注释不是写给机器看的,是写给下一个接手的人看的。网站API源码这东西,写得好不好,不看用了什么框架,看的是有没有把边界情况当回事。参数会不会被篡改,权限有没有越界,错误能不能追踪。这些点做到了,代码丑一点也能用。做不到,再漂亮的架构也是纸糊的。
顶: 6635踩: 3946






评论专区