最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
ThinkPHP 5.1 防止 API 接口参数篡改的签名算法防刷
时间:2026-07-12 09:22:03 编辑:袖梨 来源:一聚教程网
根本原因是签名算法漏校验timestamp、nonce未去重、拼接用urlencode而非rawurlencode导致HMAC-SHA256不一致;验签必须在中间件中统一处理,严禁放在控制器内。
ThinkPHP 5.1 项目上线后遭遇批量伪造下单请求,参数被恶意篡改却未被拦截——根本原因不是没加签名,而是签名算法漏掉了 timestamp 校验、nonce 未去重、拼接字符串时用了 urlencode 而非 rawurlencode,导致服务端与客户端算出的 HMAC-SHA256 值永远不一致。
签名验证必须放在中间件里
新建中间件:执行 php think make:middleware CheckApiSign,在 app/middleware.php 中注册,确保它排在路由解析之后、业务控制器之前。
中间件 handle 方法开头就提取签名,失败立即返回 json(['code'=>401,'msg'=>'sign invalid']) 并终止流程,不放行到任何控制器。
【关键】控制器里写验签等于把锁装在屋里——恶意参数已触发日志写入、库存扣减甚至数据库事务,验签失去意义。
立即学习“PHP免费学习笔记(深入)”;
统一获取原始参数并归一化
第一步:调用 $raw = $request->getInput() 一次性读取 php://input 流;若为空,则 fallback 到 file_get_contents('php://input')。
第二步:根据 $request->header('content-type') 分支处理:
含 application/json → json_decode($raw, true);
否则 → parse_str($raw, $body)。
第三步:合并参数:$params = array_merge($request->get(), $body ?: []);,再对每个值执行 trim(str_replace(["r","n"], '', (string)$v)) 清除隐藏字符。
第四步:剔除非业务字段:unset($params['sign'], $params['signature'], $params['timestamp'], $params['nonce']);,但必须先 isset() 判断是否存在,避免 Notice 报错。
构造签名原文的三要素
方法一:基础拼接(适用于 GET/简单表单)
对 $params 执行 ksort($params, SORT_STRING);
遍历拼接 rawurlencode($k).'='.rawurlencode($v),用 & 连接;
追加 ×tamp=xxx&nonce=yyy(注意:timestamp 必须是客户端传入的 Unix 秒级时间戳);
最后拼上密钥:$data = $query_string . '×tamp=' . $ts . '&nonce=' . $nonce . '&key=' . config('api.sign_key');。
方法二:带 HTTP 方法和路径(防接口挪用)
取 $method = strtoupper($request->method()); 和 $uri = parse_url($request->url(), PHP_URL_PATH);;
签名原文格式:$method . "n" . $uri . "n" . $query_string . "n";
【关键】换行符必须是 n,不能是 rn,否则哈希值错位。
计算与比对签名
用 hash_hmac('sha256', $data_string, config('api.sign_key'), true) 计算二进制签名,再 base64_encode() 编码为字符串。
从 Header 取签名:$clientSign = $request->header('X-Signature');,绝不用 $request->param('sign')——后者可能被业务参数污染。
用 hash_equals($serverSign, $clientSign) 比对,防止时序攻击;ThinkPHP 5.1 需自行引入该函数或使用 ==(低风险场景)。
校验 timestamp:取 abs(time() - $ts) > 300,超时直接拒掉;nonce 存 Redis:Redis::setex('nonce:' . $nonce, 600, 1),若已存在则验签失败。
相关文章
- 迷你世界炎狱魔龙如何获得 炎狱魔龙技能图鉴 07-20
- 迷你世界厨房修建攻略 迷你世界厨房搭建方法 07-20
- 洛克王国世界s3赛季什么时候开始 07-20
- 绝区零希格莉德立绘合集 希格莉德值得抽吗 07-20
- 《明日方舟:终末地》塔晶系统介绍 07-20
- 金铲铲之战s18索拉卡羁绊技能分享 07-20