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

PHP 實作登入異常 IP 偵測:資料庫歷史比對與客戶端 IP 取得最佳實踐

     編輯:PHP 綜合知識

帳號安全防護中,偵測「非常用裝置/地點登入」是基本需求。本文示範如何結合客戶端 IP 取得、資料庫歷史登入記錄比對、閾值判斷,實作一個輕量級異常 IP 標記功能,適用於各類 PHP 框架。

核心邏輯

  1. 取得當前請求的真實客戶端 IP。
  2. 若與使用者綁定的「常用 IP」一致 → 正常(藍字)。
  3. 否則查詢資料庫:該帳號歷史上從此 IP 登入次數。
  4. 次數超過閾值(如 10 次) → 視為信任 IP(藍字);否則 → 異常 IP(紅字標警)。

完整實作代碼

/**
 * 判斷登入 IP 是否異常
 *
 * @param string $bindIp 使用者綁定/上次登入 IP
 * @param string $username 使用者帳號
 * @return string HTML 字串,含顏色標記
 */
function checkLoginIp(string $bindIp, string $username): string {
    $currentIp = getClientIp();

    if ($bindIp === $currentIp) {
        return '登入 IP:' . $currentIp . '';
    }

    // 查詢歷史登入次數(假設使用 ThinkPHP 模型,可替換為 PDO/DBAL)
    $count = \think\Db::name('login_log')
        ->where('username', $username)
        ->where('ip', $currentIp)
        ->count();

    $threshold = 10; // 信任閾值,可從配置讀取
    $color = $count > $threshold ? 'blue' : 'red';
    $label = $count > $threshold ? '登入 IP' : '異常 IP';

    return '' . $label . ':' . $currentIp . '';
}

/**
 * 取得真實客戶端 IP(支援代理、CDN、負載均衡)
 */
function getClientIp(): string {
    $headers = [
        'HTTP_CLIENT_IP',
        'HTTP_X_FORWARDED_FOR', // 可能包含多個 IP,取第一個非 unknown
        'HTTP_X_REAL_IP',       // Nginx proxy_set_header
        'REMOTE_ADDR'
    ];

    foreach ($headers as $header) {
        $value = $_SERVER[$header] ?? '';
        if ($value) {
            // X-Forwarded-For 可能是 "client, proxy1, proxy2"
            $ips = array_map('trim', explode(',', $value));
            foreach ($ips as $ip) {
                if ($ip !== 'unknown' && filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
                    return $ip;
                }
            }
        }
    }

    return $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
}

資料表設計建議

CREATE TABLE `login_log` (
    `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
    `username` VARCHAR(64) NOT NULL COMMENT '登入帳號',
    `ip` VARBINARY(16) NOT NULL COMMENT 'IPv4/IPv6 二進位儲存,INET6_ATON()',
    `user_agent` VARCHAR(255) DEFAULT NULL,
    `status` TINYINT NOT NULL DEFAULT 1 COMMENT '1成功 0失敗',
    `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (`id`),
    INDEX `idx_user_ip` (`username`, `ip`),
    INDEX `idx_created` (`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

IP 建議用 VARBINARY(16) 儲存(INET6_ATON()/INET6_NTOA()),節省空間且利於範圍查詢。

進階強化方向

  • 裝置指紋:結合 User-Agent、Canvas 指紋、Cookie,判斷「同一裝置」而非單純 IP。
  • 地理位置比對:使用 IP 地理庫(MaxMind GeoIP2、ip2region),異地登入直接觸發驗證碼/雙因子認證。
  • 風險評分模型:IP 信譽、登入頻率、失敗次數、時間異常綜合評分,動態調整防護等級。
  • 非同步記錄:登入日誌寫入 MQ,消費者落庫,不阻塞主流程。

安全提醒

  1. 不可信任單一 Header:X-Forwarded-For 可偽造,必須配合伺服器層(Nginx/Apache)設定 real_ip 模組,只信任可信代理層傳遞的 Header。
  2. IPv6 支援:確保資料庫、驗證函式、地理庫皆支援 IPv6。
  3. 隱私合規:IP 屬個人資料,記錄需告知使用者,保留期限符合 GDPR/個資法。

異常 IP 偵測是帳號安全的第一道防線。從正確取得真實 IP 開始,結合歷史行為建模,再逐步引入裝置指紋與風險評分,構建分層防護體系。

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