簡單的 Session 限流可緩解小規模 CC 攻擊 (HTTP Flood) 與惡意快速重新整理。本文提供基礎防護代碼,並說明其局限性與生產環境建議架構。
<?php
// 1. 阻擋代理 IP (可選,易誤傷企業用戶)
if (!empty($_SERVER['HTTP_VIA']) || !empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
// exit('Access Denied: Proxy detected'); // 建議改為記錄日誌而非直接阻擋
}
// 2. Session 限流核心
session_start();
$windowSeconds = 3; // 時間窗 (秒)
$maxRequests = 5; // 最大請求數
$now = time();
$key = 'ratelimit_' . md5($_SERVER['REQUEST_URI'] ?? 'global');
if (!isset($_SESSION[$key])) {
$_SESSION[$key] = ['count' => 1, 'start' => $now];
} else {
$data = &$_SESSION[$key];
if ($now - $data['start'] < $windowSeconds) {
$data['count']++;
if ($data['count'] > $maxRequests) {
// 觸發限流
http_response_code(429);
header('Retry-After: ' . $windowSeconds);
exit('請求過於頻繁,請稍後再試 (429 Too Many Requests)');
}
} else {
// 窗口重置
$data['count'] = 1;
$data['start'] = $now;
}
}
// 正常業務邏輯繼續...
echo "請求通過";
class RateLimiter {
private $redis;
private $limits = [
'global' => [100, 60], // 100 req/min 全站
'ip' => [30, 60], // 30 req/min 單 IP
'user' => [60, 60], // 60 req/min 登入用戶
'endpoint' => [10, 10], // 10 req/10s 特定端點
'login' => [5, 300], // 5 req/5min 登入端點
];
public function __construct(Redis $redis) { $this->redis = $redis; }
public function check(string $scope, string $id): bool {
[$max, $window] = $this->limits[$scope] ?? [100, 60];
$key = "ratelimit:$scope:$id";
$pipe = $this->redis->multi();
$pipe->incr($key);
$pipe->expire($key, $window);
$results = $pipe->exec();
$current = $results[0];
if ($current > $max) {
$ttl = $this->redis->ttl($key);
throw new RateLimitExceededException($scope, $max, $window, $ttl);
}
return true;
}
}
// 使用
$limiter = new RateLimiter($redis);
try {
$limiter->check('ip', $_SERVER['REMOTE_ADDR']);
$limiter->check('endpoint', $_SERVER['REQUEST_URI']);
// 通過
} catch (RateLimitExceededException $e) {
http_response_code(429);
header("Retry-After: {$e->ttl}");
exit(json_encode(['error' => 'rate_limited', 'retry_after' => $e->ttl]));
}
| 層級 | 工具/位置 | 特點 |
|---|---|---|
| 邊緣/雲端 | Cloudflare WAF, AWS Shield, Alibaba Cloud Anti-DDoS | 吸收大流量攻擊、隱藏源站 IP、零程式碼改動 |
| 負載均衡器 | Nginx limit_req_module, HAProxy stick-table | 高效能、共享記憶體、支援漏桶/令牌桶 |
| 應用層 | Redis + Lua 腳本 / PHP 中介軟體 | 精細業務邏輯、分散式一致、可自訂回應 |
| 資料庫 | 連線池限制、查詢超時 | 防止資源耗盡 |
# nginx.conf http 區塊
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;
server {
location /api/ {
limit_req zone=api burst=20 nodelay;
limit_req_status 429;
proxy_pass https://php_upstream;
}
location /login {
limit_req zone=login burst=3 nodelay;
limit_req_status 429;
}
}
session_start() 會阻塞,反而加劇延遲。單純 PHP Session 限流僅適合極小型專案或臨時緩解,正式上線請採用多層防護體系。