基于Fat Free Framework,如何防止高分提交POST请求被篡改?
高分提交防篡改的优化方案
针对你用Fat Free Framework开发小游戏合集时遇到的参数篡改问题,给你几个比全量改写session逻辑更高效的方案:
1. HMAC请求签名(最推荐)
这个方案不用大改现有提交逻辑,核心是给参数加个“防伪标签”,后端通过验证标签合法性判断参数是否被篡改:
实现步骤:
- 游戏初始化阶段:后端生成随机签名密钥,存入用户session并返回给前端
// Fat Free框架内的代码示例 $signingKey = bin2hex(random_bytes(16)); // 生成16字节随机密钥转十六进制 $f3->set('SESSION.signing_key', $signingKey); // 将密钥通过游戏初始化接口响应返回给前端 echo json_encode(['signing_key' => $signingKey]); - 前端提交高分时:用HMAC算法(如SHA256)将
game、score与签名密钥拼接生成签名,随参数一起提交// 假设已获取后端返回的signingKey const game = "Tetris"; const score = player.score; // 用CryptoJS生成签名,注意拼接规则前后端必须完全一致 const signature = CryptoJS.HmacSHA256(`${game}:${score}`, signingKey).toString(); $.ajax({ "url": "/submitHighscore", "type": "post", "data": { "game": game, "score": score, "signature": signature } }); - 后端验证逻辑:从session取出密钥,用相同规则计算签名并与前端传入的对比,一致则执行入库
// 在/submitHighscore路由中 $game = $f3->get('POST.game'); $score = $f3->get('POST.score'); $receivedSignature = $f3->get('POST.signature'); $signingKey = $f3->get('SESSION.signing_key'); // 计算预期签名 $expectedSignature = hash_hmac('sha256', "$game:$score", $signingKey); if ($expectedSignature === $receivedSignature) { // 签名合法,执行高分入库逻辑 } else { // 签名不匹配,拒绝请求 $f3->error(403, 'Invalid request'); }
优点:参数被篡改后签名必然失效,还可结合一次性随机数(Nonce)防重放攻击,代码改动量极小。
2. 后端分数合理性校验(兜底必备)
不管用什么前端防篡改方案,后端都应该加一层基于游戏规则的分数校验,从逻辑层面过滤异常分数:
- 示例代码(根据不同游戏规则调整):
function isScoreValid($game, $score) { switch($game) { case 'Tetris': // 假设单局最高分不超过10000,且分数为100的倍数(按实际规则调整) return $score > 0 && $score <= 10000 && $score % 100 === 0; case 'Snake': // 蛇形游戏的分数规则校验 return $score > 0 && $score <= 5000; default: return false; } } // 在提交逻辑中调用校验 if (isScoreValid($game, $score)) { // 分数合法,继续执行 } else { $f3->error(400, 'Invalid score'); }
优点:完全不需要改动前端代码,纯后端逻辑就能过滤大部分离谱的篡改分数。
3. 轻量化Session方案(折中选择)
如果不想加签名逻辑,可以只在session中存储用户当前正在玩的游戏,前端提交时只传score,后端对比session中的游戏与前端传入的game是否一致,再结合分数校验:
- 游戏开始时:
$f3->set('SESSION.current_game', 'Tetris'); - 后端验证:
$submittedGame = $f3->get('POST.game'); $currentGame = $f3->get('SESSION.current_game'); if ($submittedGame !== $currentGame) { $f3->error(403, 'Invalid game'); } // 再执行分数合理性校验
优点:改动量远小于全量存储分数的session方案,能有效防止篡改game参数,配合分数校验可覆盖大部分篡改场景。
内容的提问来源于stack exchange,提问作者nameless
相关产品推荐
相关产品推荐

