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

PHP 利用 Session 防止頁面重複提交與惡意刷新

     編輯:PHP 綜合知識

核心思路

結合 **用戶 IP**、**提交表單關鍵字段**、**時間戳** 生成唯一 Session Key,限制單位時間內同一用戶對同一業務操作的提交頻率。

完整實現代碼(b.php)

<?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}";
?>

前端表單示例(a.html)

<!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>

關鍵點解析

  1. IP 獲取:優先 HTTP_X_FORWARDED_FOR(代理/負載均衡環境),回退 HTTP_CLIENT_IP、REMOTE_ADDR。
  2. Session Key 設計:md5(IP + 業務字段 + 密鑰) 確保不同業務操作互不干擾,密鑰防止 Key 被預測。
  3. 時間窗口:$allowTime 可根據業務調整(如支付 60s、搜索 3s、刷新 1s)。
  4. 響應碼:使用 429 Too Many Requests 比 404 更符合語義,便於前端識別並提示用戶。
  5. Session 清理:長期運行需定期清理過期 Session(PHP 默認 gc 機制通常足夠)。

進階防禦:Referer 檢查與 CSRF Token

<?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 驗證失敗');
}
?>

生產環境建議

  • 使用 Redis 替代文件 Session,支持集群、TTL 自動過期、原子操作。
  • 引入限流庫(如 symfony/rate-limiter)實現更精細的限流策略(令牌桶、漏桶、滑動窗口)。
  • 關鍵業務(登錄、註冊、支付)結合圖形/短信/郵箱驗證碼多因子驗證。
  • 記錄刷新日誌,分析異常 IP 行為,配合防火牆封禁。

Session 防刷新是輕量級的應用層限流手段,配合 CSRF Token、驗證碼、WAF 可構建較完善的防刷體系。

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