結合 **用戶 IP**、**提交表單關鍵字段**、**時間戳** 生成唯一 Session Key,限制單位時間內同一用戶對同一業務操作的提交頻率。
<?php
// 僅允許 POST 訪問
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(404);
exit('頁面不存在');
}
session_start();
// 獲取表單關鍵字段(根據業務調整)
$fieldA = $_POST['a'] ?? '';
$fieldB = $_POST['b'] ?? '';
// 防刷新時間窗口(秒)
$allowTime = 30;
/**
* 獲取客戶端真實 IP
*/
function getRealIp() {
static $ip = null;
if ($ip !== null) return $ip;
if (isset($_SERVER)) {
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
foreach ($arr as $xip) {
$xip = trim($xip);
if ($xip !== 'unknown') { $ip = $xip; break; }
}
} elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
} else {
$ip = $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
}
} else {
$ip = getenv('HTTP_X_FORWARDED_FOR') ?: getenv('HTTP_CLIENT_IP') ?: getenv('REMOTE_ADDR') ?: '0.0.0.0';
}
// 簡單格式校驗
if (!preg_match('/^[\d\.]{7,15}$/', $ip)) $ip = '0.0.0.0';
return $ip;
}
$clientIp = getRealIp();
// 生成唯一 Session Key:IP + 業務字段 + 密鑰
$sessionKey = md5($clientIp . $fieldA . $fieldB . 'SALT_KEY'); // 建議加入項目級密鑰
// 檢查時間間隔
$lastTime = $_SESSION[$sessionKey] ?? 0;
$now = time();
if ($now - $lastTime < $allowTime) {
http_response_code(429); // Too Many Requests
exit("來自 {$clientIp} 的請求過於頻繁,請 {$allowTime} 秒後再試");
}
// 更新時間戳
$_SESSION[$sessionKey] = $now;
// ===== 業務邏輯開始 =====
echo "處理業務邏輯... 字段A: {$fieldA}, 字段B: {$fieldB}";
?>
<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>提交頁面</title></head><body>
<form action="b.php" method="post">
<input type="hidden" name="a" value="order_submit">
<input type="hidden" name="b" value="product_123">
<button type="submit">提交訂單</button>
</form>
</body></html>
HTTP_X_FORWARDED_FOR(代理/負載均衡環境),回退 HTTP_CLIENT_IP、REMOTE_ADDR。md5(IP + 業務字段 + 密鑰) 確保不同業務操作互不干擾,密鑰防止 Key 被預測。$allowTime 可根據業務調整(如支付 60s、搜索 3s、刷新 1s)。429 Too Many Requests 比 404 更符合語義,便於前端識別並提示用戶。<?php
// 可選:Referer 白名單檢查(注意 Referer 可偽造、部分瀏覽器不發送)
$allowedHosts = ['example.com', 'www.example.com'];
$referer = $_SERVER['HTTP_REFERER'] ?? '';
$refererHost = parse_url($referer, PHP_URL_HOST);
if ($refererHost && !in_array($refererHost, $allowedHosts)) {
http_response_code(403);
exit('非法請求來源');
}
// 必須:CSRF Token 防跨站請求偽造
if (!isset($_POST['csrf_token']) || $_POST['csrf_token'] !== ($_SESSION['csrf_token'] ?? '')) {
http_response_code(403);
exit('CSRF Token 驗證失敗');
}
?>
symfony/rate-limiter)實現更精細的限流策略(令牌桶、漏桶、滑動窗口)。Session 防刷新是輕量級的應用層限流手段,配合 CSRF Token、驗證碼、WAF 可構建較完善的防刷體系。