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

PHP 獲取用戶真實 IP 地址的 5 種實用方法

     編輯:PHP 綜合知識

前言

在 Web 開發中,獲取用戶的真實 IP 地址是常見需求,例如用於日誌記錄、訪問控制、地理定位或防刷機制。然而,由於代理服務器、負載均衡器、CDN 等中間層的存在,直接讀取 $_SERVER['REMOTE_ADDR'] 往往只能拿到代理的 IP,而非用戶真實 IP。本文整理了 5 種 PHP 獲取用戶 IP 的方法,並說明各自的適用場景與注意事項。

方法一:直接讀取 REMOTE_ADDR(最基礎)

這是最簡單的方式,直接從 $_SERVER 超全局變量獲取:

<?php
$ip = $_SERVER["REMOTE_ADDR"];
echo $ip;
?>

適用場景:無代理、無 CDN 的直連環境。
缺點:若用戶經過代理或 CDN,得到的將是代理服務器 IP,而非真實用戶 IP。

方法二:判斷 HTTP_VIA 與 HTTP_X_FORWARDED_FOR

稍微進階一點,先檢查是否存在 HTTP_VIA(代理標識),若存在則嘗試從 HTTP_X_FORWARDED_FOR 取得原始 IP:

<?php
$user_IP = ($_SERVER["HTTP_VIA"]) ? $_SERVER["HTTP_X_FORWARDED_FOR"] : $_SERVER["REMOTE_ADDR"];
$user_IP = ($user_IP) ? $user_IP : $_SERVER["REMOTE_ADDR"];
echo $user_IP;
?>

注意:HTTP_X_FORWARDED_FOR 可能包含多個 IP(格式如 client, proxy1, proxy2),此寫法未做解析,僅取整個字符串。

方法三:封裝函數獲取真實 IP(推薦)

這是一個較完善的函數,會依序檢查 HTTP_CLIENT_IP、HTTP_X_FORWARDED_FOR,並過濾掉私有 IP 段(10.x、172.16.x、192.168.x),返回第一個公網 IP:

<?php
function getRealIp() {
    $ip = false;
    if (!empty($_SERVER["HTTP_CLIENT_IP"])) {
        $ip = $_SERVER["HTTP_CLIENT_IP"];
    }
    if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $ips = explode(", ", $_SERVER['HTTP_X_FORWARDED_FOR']);
        if ($ip) {
            array_unshift($ips, $ip);
            $ip = false;
        }
        for ($i = 0; $i < count($ips); $i++) {
            if (!preg_match("/^(10|172\.16|192\.168)\./", $ips[$i])) {
                $ip = $ips[$i];
                break;
            }
        }
    }
    return ($ip ? $ip : $_SERVER['REMOTE_ADDR']);
}
echo getRealIp();
?>

優點:過濾內網 IP,提高獲取真實公網 IP 的準確度。
注意:原代碼使用已棄用的 eregi,已改用 preg_match。

方法四:兼容舊版 PHP 的多重判斷

早期 PHP 版本常用 $HTTP_SERVER_VARS 與 getenv(),此方法兼容性極佳:

<?php
if ($HTTP_SERVER_VARS["HTTP_X_FORWARDED_FOR"]) {
    $ip = $HTTP_SERVER_VARS["HTTP_X_FORWARDED_FOR"];
} elseif ($HTTP_SERVER_VARS["HTTP_CLIENT_IP"]) {
    $ip = $HTTP_SERVER_VARS["HTTP_CLIENT_IP"];
} elseif ($HTTP_SERVER_VARS["REMOTE_ADDR"]) {
    $ip = $HTTP_SERVER_VARS["REMOTE_ADDR"];
} elseif (getenv("HTTP_X_FORWARDED_FOR")) {
    $ip = getenv("HTTP_X_FORWARDED_FOR");
} elseif (getenv("HTTP_CLIENT_IP")) {
    $ip = getenv("HTTP_CLIENT_IP");
} elseif (getenv("REMOTE_ADDR")) {
    $ip = getenv("REMOTE_ADDR");
} else {
    $ip = "Unknown";
}
echo $ip;
?>

適用場景:極老舊的 PHP 環境(PHP 4.x 時代),現代項目不建議使用。

方法五:僅使用 getenv() 獲取

簡潔版,僅依賴 getenv() 函數:

<?php
if (getenv('HTTP_CLIENT_IP')) {
    $onlineip = getenv('HTTP_CLIENT_IP');
} elseif (getenv('HTTP_X_FORWARDED_FOR')) {
    $onlineip = getenv('HTTP_X_FORWARDED_FOR');
} elseif (getenv('REMOTE_ADDR')) {
    $onlineip = getenv('REMOTE_ADDR');
} else {
    $onlineip = $HTTP_SERVER_VARS['REMOTE_ADDR'];
}
echo $onlineip;
?>

最佳實踐建議

  • 優先使用方法三,封裝為通用函數放入公共庫。
  • 若項目部署在 CDN(如 Cloudflare)或負載均衡器後方,請務必配置信任代理頭(如 CF-Connecting-IP、X-Real-IP),並在 PHP 中優先讀取這些頭。
  • 永遠不要完全信任客戶端傳來的 IP 頭,關鍵業務(如封禁、計費)應結合應用層邏輯驗證。

總結

獲取用戶真實 IP 看似簡單,實則需根據部署架構選擇合適策略。建議在項目初期統一封裝 getClientIp() 函數,並根據實際網絡環境持續優化,避免日後排查日誌時發現 IP 全是代理地址的尷尬局面。

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