
本文介绍通过 HTTP 方法校验(POST)、Referer 检查、一次性 Token 及服务器端路由控制,安全阻止用户直接访问 test.php?action=try 等敏感接口,防止绕过前端逻辑触发奖励发放。
本文介绍通过 http 方法校验(post)、referer 检查、一次性 token 及服务器端路由控制,安全阻止用户直接访问 `test.php?action=try` 等敏感接口,防止绕过前端逻辑触发奖励发放。
在基于轮盘抽奖(如 winwheel.js)的 Web 应用中,test.php 承担核心业务逻辑——生成随机中奖结果、扣减积分、发放奖励。但若该文件仅靠 ?action=try 参数暴露在 GET 请求中,攻击者可轻松在浏览器地址栏手动访问 test.php?action=try,反复触发 _Spin() 和 payWheel(),导致积分滥扣与奖励盗刷。单纯依赖前端 JavaScript 控制是不安全的,所有关键校验必须落在服务端。
✅ 推荐方案:多层防护组合(非单一措施)
1. 强制使用 POST + CSRF Token(最有效实践)
将请求方式从 GET 升级为带签名的 POST,并引入一次性 Token,从根本上阻断地址栏直接访问。
前端(Custom.js)调整:
function startSpin() {
if (wheelSpinning === false) {
// 从页面 meta 或 hidden input 中读取 CSRF token(服务端渲染时注入)
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content');
$.post("test.php", {
action: "try",
_token: csrfToken // 提交 token
}, function(data) {
console.log(data);
WheelOfFortune.rotationAngle = 0;
WheelOfFortune.animation.spins = 10;
WheelOfFortune.animation.stopAngle = data.lastPosition || 0;
WheelOfFortune.startAnimation();
wheelSpinning = true;
}).fail(function(xhr) {
alert("抽奖失败:" + (xhr.responseJSON?.message || "网络错误"));
});
}
}后端(test.php)强化校验:
立即学习“PHP免费学习笔记(深入)”;
<?php
session_start();
// 1. 必须为 POST 请求
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
echo json_encode(['error' => 'Method not allowed']);
exit;
}
// 2. 校验 CSRF Token(需与前端一致)
if (!isset($_POST['_token']) || !hash_equals($_SESSION['csrf_token'] ?? '', $_POST['_token'])) {
http_response_code(403);
echo json_encode(['error' => 'Invalid or expired token']);
exit;
}
// 3. 校验用户登录状态与积分(示例)
if (!isset($_SESSION['user_id']) || $_SESSION['credit'] < 100) {
echo json_encode(['error' => 'Insufficient credits']);
exit;
}
// 4. 生成新 Token(防重复提交)
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
// 执行业务逻辑
if ($_POST['action'] === 'try') {
$result = _Spin(rand(1, 10), 100);
echo json_encode([
'success' => true,
'lastPosition' => $result['stopAngle'] ?? 0,
'reward' => $result['item'] ?? 'Thanks!'
]);
}
?>⚠️ 注意:
session_start()必须在任何输出前调用;hash_equals()防止时序攻击;Token 每次使用后立即刷新。
2. 补充防护:Referer 与 AJAX 头校验(辅助手段)
作为第二道防线,可检查请求来源是否为本站且含 X-Requested-With: XMLHttpRequest:
// 在 test.php 开头追加
if (empty($_SERVER['HTTP_X_REQUESTED_WITH']) ||
strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) !== 'xmlhttprequest') {
http_response_code(403);
exit('Direct access denied.');
}⚠️ 注意:Referer 可被伪造,不可单独依赖,仅作辅助。
3. 服务器配置级防护(Nginx/Apache)
在 Web 服务器层面拒绝对敏感 PHP 文件的 GET 访问:
# Nginx 示例:禁止 GET 方式访问 test.php
location ~ ^/test\.php$ {
if ($request_method = GET) {
return 403;
}
}✅ 总结:安全设计原则
-
永远不要信任客户端:JS 中的
if (wheelSpinning == false)仅用于 UX,不能替代服务端校验; -
最小权限原则:
test.php不应处理 HTML 渲染,只响应 JSON,且无输出无关内容; -
状态一致性:积分扣减与奖励发放必须在单个事务中完成(如 MySQL
START TRANSACTION),避免中间态被利用; -
日志审计:记录高频异常请求(如 1 秒内多次
/test.php),便于风控追踪。
通过 POST + Token + Session + 服务端逻辑四重校验,即可彻底杜绝 test.php?action=try 的非法直连,保障抽奖系统的公平性与资金安全。



















