在 Web 開發中,準確獲取用戶的真實 IP 地址是一項基礎且關鍵的需求。由於代理服務器、負載均衡器、CDN 等網絡設備的廣泛使用,單純依賴 $_SERVER['REMOTE_ADDR'] 往往無法獲得客戶端的真實 IP。本文將深入解析 PHP 判斷訪問 IP 的核心邏輯,並提供一個健壯、可復用的函數實現。
當請求經過代理層時,原始客戶端 IP 通常會被附加在特定的 HTTP 頭部中。獲取真實 IP 的標準邏輯是按優先級檢查以下變量:
client, proxy1, proxy2,取第一個非未知 IP 即為真實客戶端 IP。get_client_ip() 函數以下函數封裝了上述邏輯,並增加了正則驗證確保返回格式合法的 IPv4 地址:
<?php
/**
* 獲取客戶端真實 IP 地址
* @return string 真實 IP 或 'unknown'
*/
function get_client_ip() {
$ip = 'unknown';
// 1. 檢查 HTTP_CLIENT_IP
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
}
// 2. 檢查 HTTP_X_FORWARDED_FOR (可能包含多個 IP,取第一個有效值)
elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
foreach ($ips as $single_ip) {
$single_ip = trim($single_ip);
if (filter_var($single_ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
$ip = $single_ip;
break;
}
}
// 如果沒找到公網 IP,退而求其次取第一個
if ($ip === 'unknown') {
$ip = trim($ips[0]);
}
}
// 3. 最後 fallback 到 REMOTE_ADDR
elseif (!empty($_SERVER['REMOTE_ADDR'])) {
$ip = $_SERVER['REMOTE_ADDR'];
}
// 正則驗證 IPv4 格式 (簡易版,生產環境建議用 filter_var)
if (!preg_match('/^[\d\.]{7,15}$/', $ip)) {
return 'unknown';
}
return $ip;
}
?>
上述代碼適用於大多數場景,但在高安全性需求(如風控、支付)下,需注意:
X-Forwarded-For 等頭部由客戶端發送,惡意用戶可偽造。務必配合 Web 服務器(Nginx/Apache)在入口層清洗或重寫這些頭部,只信任來自已知代理 IP 的轉發頭。filter_var($ip, FILTER_VALIDATE_IP) 同時兼容 IPv6。CF-Connecting-IP、X-Forwarded-For 的特定處理邏輯)。獲取真實 IP 的本質是「信任鏈」的建立。通過規範的代理配置與分層驗證代碼,可有效解決 90% 以上的場景需求。希望本文提供的函數能為你的 PHP 專案帶來便利。