如何检测HTTP请求是否被Burp Suite等客户端工具篡改及校验实现
HTTP请求防篡改实现方案
你提到的在请求中增加完整性哈希做校验是可行的防篡改方案,核心逻辑是前后端共享一个不对外公开的密钥,按统一规则计算请求参数的哈希值,服务端二次计算后做对比,哈希不一致即可判定请求被篡改。
注意:前端所有代码都可以被逆向破解,该方案只能提升篡改门槛,无法完全杜绝被Burp Suite等工具伪造请求的情况,敏感操作必须配合后端的业务逻辑二次校验。
实现示例
前置约定
- 前后端共享固定密钥
SALT,建议用户登录成功后由后端返回存储在前端会话中,定期刷新,不要硬编码在前端静态代码里。 - 前后端统一使用
SHA256算法计算哈希,参数统一按键名ASCII码升序拼接。
1. 客户端(JS)实现
// 这里的SALT建议从登录接口返回的会话信息中获取,不要硬编码 const REQUEST_SALT = "your_shared_secret_salt"; // 收集所有请求参数 const params = { token: "ExampleToken", email: "example@email.com", subscription_level: 3 }; // 参数按键名ASCII码升序排列 const sortedKeys = Object.keys(params).sort(); let signStr = ""; sortedKeys.forEach(key => { signStr += `${key}=${params[key]}&`; }); // 拼接密钥后计算哈希 signStr += `salt=${REQUEST_SALT}`; // 用浏览器原生API计算SHA256哈希 const signHash = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(signStr)) .then(buf => Array.from(new Uint8Array(buf)).map(b => b.toString(16).padStart(2, '0')).join('')); // 把哈希加到FormData里,也可以放在自定义请求头比如X-Request-Sign里 var fd = new FormData(); for (let key in params) { fd.append(key, params[key]); } fd.append("sign", signHash); axios.post("https://urlToTheRestApi/file.php", fd).then(() => { //do some stuff })
2. 服务端(PHP)实现
// 前后端一致的密钥,存在服务端配置里不要泄露 define('REQUEST_SALT', 'your_shared_secret_salt'); // 先校验签名是否存在 if (!isset($_POST['sign'])) { die("非法请求"); } $clientSign = $_POST['sign']; unset($_POST['sign']); // 按同样规则拼接参数 ksort($_POST); $signStr = ""; foreach ($_POST as $key => $value) { $signStr .= "{$key}={$value}&"; } $signStr .= "salt=".REQUEST_SALT; $serverSign = hash('sha256', $signStr); // 对比哈希 if ($serverSign !== $clientSign) { die("请求被篡改"); } // 哈希校验通过后再做业务逻辑校验 if(isset($_POST['token']) && isset($_POST['email']) && isset($_POST['subscription_level'])) { // 注意:subscription_level这类权限相关的字段,建议后端从用户表查询校验,不要完全信任前端传值 //do some stuff }
额外优化建议
- 必须开启HTTPS,避免明文传输下密钥和签名规则被直接抓包获取
- 可以在参数中增加当前时间戳,签名校验同时校验时间差,比如请求时间和服务端时间差超过5分钟直接拒绝,可防范重放攻击
- 前端代码可以做混淆处理,提升签名规则和密钥的逆向难度
内容的提问来源于stack exchange,提问作者Zagrios
相关产品推荐
相关产品推荐

