首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 防止頁面惡意刷新/CC 攻擊的多層防禦策略與代碼實現

     編輯:PHP 綜合知識

威脅模型

  • 惡意刷新 (F5/腳本):單用戶高頻請求,消耗 PHP Worker、DB 連接、頻寬。
  • CC 攻擊 (HTTP Flood):分佈式 IP、偽造 User-Agent、針對動態頁面(搜尋、評論、登入)。
  • 掃描/爬蟲:遍歷 URL、提交表單、消耗資源。

防禦分層架構

層級位置手段優點缺點
1. 基礎設施Nginx/Cloudflare/WAF限流 (limit_req)、IP 黑名單、驗證碼、JS 挑戰不佔用 PHP、攔截早、支援分佈式需運維權限、誤傷風險
2. PHP 進程框架中間件/公共控制器Session/Redis 計數、Token 驗證、蜜罐字段邏輯靈活、可結合業務狀態消耗 PHP Worker、單機難擴展
3. 應用業務具體控制器動作表單 Token、提交間隔、設備指紋、風控引擎精準業務語義、用戶體驗可控開發成本高、易遺漏

PHP 層級實現:三種進階方案

方案一:Redis 滑動窗口限流(推薦生產環境)

<?php
class RateLimiter {
    private $redis;
    private $prefix = 'ratelimit:';

    public function __construct(\Redis $redis) { $this->redis = $redis; }

    /**
     * @param string $key     唯一標識 (IP:route, user_id:action)
     * @param int    $limit   最大請求數
     * @param int    $window  時間窗口(秒)
     * @return bool  true=允許, false=拒絕
     */
    public function allow(string $key, int $limit, int $window): bool {
        $key = $this->prefix . $key;
        $now = microtime(true);
        $windowStart = $now - $window;

        $pipe = $this->redis->multi();
        $pipe->zRemRangeByScore($key, 0, $windowStart); // 清理過期
        $pipe->zCard($key);                              // 當前計數
        $pipe->zAdd($key, $now, $now . ':' . uniqid());  // 記錄本次請求
        $pipe->expire($key, $window + 1);                // 保護性過期
        $results = $pipe->exec();

        $current = (int)$results[1];
        return $current < $limit;
    }
}

// 使用:公共控制器基類
class BaseController extends Controller {
    protected function _initialize() {
        $limiter = new RateLimiter(new Redis());
        $ip = request()->ip();
        $route = request()->module() . ':' . request()->controller() . ':' . request()->action();
        
        // 登入/註冊/搜尋 更嚴格
        $strict = in_array(request()->action(), ['login', 'register', 'search', 'comment']);
        $limit = $strict ? 10 : 60; // 次/分鐘
        $window = 60;

        if (!$limiter->allow("ip:$ip:$route", $limit, $window)) {
            header('HTTP/1.1 429 Too Many Requests');
            exit(json_encode(['code' => 429, 'msg' => '請求過於頻繁,請稍後再試']));
        }
    }
}

方案二:表單 Token + 時間戳雙重驗證(防重複提交/掃描)

<?php
// 生成 Token (放入 Session/Redis)
function generate_form_token(string $formName): string {
    $token = bin2hex(random_bytes(16));
    $data = ['token' => $token, 'time' => time(), 'count' => 0];
    $_SESSION["form_token_$formName"] = $data;
    return $token;
}

// 驗證並消耗 Token
function verify_form_token(string $formName, string $inputToken, int $maxAge = 3600, int $maxUse = 1): bool {
    $key = "form_token_$formName";
    if (empty($_SESSION[$key])) return false;
    $data = $_SESSION[$key];
    if ($data['token'] !== $inputToken) return false;
    if (time() - $data['time'] > $maxAge) return false;
    if ($data['count'] >= $maxUse) return false;
    $data['count']++;
    $_SESSION[$key] = $data;
    return true;
}

// 視圖
<input type="hidden" name="form_token" value="{:generate_form_token('comment')}">

// 控制器
if (!verify_form_token('comment', I('post.form_token'))) {
    $this->error('表單已過期或無效,請刷新重試');
}

方案三:蜜罐字段 + 行為分析(無感防機器人)

<!-- 視圖:隱藏字段,正常用戶看不見不填,機器人傾向填寫所有字段 -->
<div style="display:none" aria-hidden="true">
    <input type="text" name="website" value="" tabindex="-1" autocomplete="off">
</div>
<input type="hidden" name="form_timestamp" value="{:time()}">

// 控制器
if (!empty(I('post.website'))) {
    // 機器人填寫了蜜罐
    log_write('Honeypot triggered: ' . request()->ip(), 'WARN');
    exit; // 靜默丟棄,不返回錯誤提示
}
$submitTime = time() - (int)I('post.form_timestamp');
if ($submitTime < 3) {
    // 人類不可能 3 秒內打開頁面並提交
    $this->error('操作過快,請稍後');
}

Nginx 級限流配置(基礎設施層必備)

# 定義限流區域 (放在 http 塊)
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=30r/m;
limit_req_zone $binary_remote_addr zone=login_limit:10m rate=5r/m;

server {
    location /api/ {
        limit_req zone=api_limit burst=20 nodelay;
        limit_req_status 429;
        proxy_pass ...;
    }
    location /login {
        limit_req zone=login_limit burst=3 nodelay;
        limit_req_status 429;
        proxy_pass ...;
    }
    # 靜態資源不限流
    location ~* \.(css|js|png|jpg|webp)$ {
        limit_req off;
        expires 1y;
    }
}

綜合防禦清單

  1. Nginx limit_req 兜底,保護 PHP-FPM 不被打爆。
  2. Cloudflare/阿里云 WAF 開啟「頻率限制」、「JS 挑戰」、「已知攻擊特徵庫」。
  3. PHP Redis 滑動窗口 針對核心業務 (登入、註冊、支付、評論) 精準限流。
  4. 表單 Token + 蜜罐 + 時間戳 防重複提交、防掃描、防機器人。
  5. 關鍵操作雙因子驗證 (短信/郵件/Google Authenticator)。
  6. 日誌審計與告警:429 響應超過閾值觸發告警,自動封禁 IP (fail2ban/iptables)。
  7. 靜態化/緩存:將可緩存頁面生成 HTML,繞過 PHP 進程,從源頭降低攻擊面。

總結

防刷新/CC 攻擊沒有銀彈,只有分層纖維。基礎設施層 (Nginx/WAF) 擋住 90% 流量洪峰,PHP 業務層 (Redis 限流 + Token + 蜜罐) 精準攔截惡意業務請求,應用層 (雙因子、風控) 保護核心資產。代碼層面以 Redis 滑動窗口 為核心,配合 表單 Token 與 蜜罐,即可構建高可用、低誤傷的防禦體系。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved