
获取客户端IP地址
函数还是太全面了。🤣
以下是一个PHP函数,用来获取客户端的IP地址,并考虑了不同的HTTP头(包括 HTTP_CLIENT_IP
、HTTP_X_REAL_IP
、HTTP_CDN_SRC_IP
和 HTTP_X_FORWARDED_FOR
)以及内网请求:
function getClientIp() {
// 优先级: HTTP_CLIENT_IP > HTTP_X_REAL_IP > HTTP_CDN_SRC_IP > HTTP_X_FORWARDED_FOR
$client_ip = '';
// 获取 HTTP_CLIENT_IP
if (isset($_SERVER['HTTP_CLIENT_IP']) && filter_var($_SERVER['HTTP_CLIENT_IP'], FILTER_VALIDATE_IP)) {
$client_ip = $_SERVER['HTTP_CLIENT_IP'];
}
// 如果没有,获取 HTTP_X_REAL_IP
elseif (isset($_SERVER['HTTP_X_REAL_IP']) && filter_var($_SERVER['HTTP_X_REAL_IP'], FILTER_VALIDATE_IP)) {
$client_ip = $_SERVER['HTTP_X_REAL_IP'];
}
// 如果没有,获取 HTTP_CDN_SRC_IP
elseif (isset($_SERVER['HTTP_CDN_SRC_IP']) && filter_var($_SERVER['HTTP_CDN_SRC_IP'], FILTER_VALIDATE_IP)) {
$client_ip = $_SERVER['HTTP_CDN_SRC_IP'];
}
// 如果没有,获取 HTTP_X_FORWARDED_FOR
elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
// X-Forwarded-For 可以是多个IP,取第一个非内网IP
$ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
foreach ($ips as $ip) {
$ip = trim($ip);
// 排除内网IP范围
if (!filter_var($ip, FILTER_VALIDATE_IP) || preg_match('/^192\.168\./', $ip) || preg_match('/^10\./', $ip) || preg_match('/^172\.(1[6-9]|2[0-9]|3[01])\./', $ip)) {
continue;
}
$client_ip = $ip;
break;
}
}
// 如果都没有找到IP,返回REMOTE_ADDR
if (empty($client_ip) && isset($_SERVER['REMOTE_ADDR'])) {
$client_ip = $_SERVER['REMOTE_ADDR'];
}
return $client_ip;
}
说明:
- HTTP_CLIENT_IP:客户端直接提供的IP地址,通常用于代理或虚拟主机环境中。
- HTTP_X_REAL_IP:负载均衡器或代理服务器传递的客户端IP地址。
- HTTP_CDN_SRC_IP:CDN或反向代理服务器传递的客户端IP。
- HTTP_X_FORWARDED_FOR:此头信息通常包含了客户端的原始IP和代理服务器的IP,多个IP由逗号分隔。我们会跳过内网IP(192.168.x.x、10.x.x.x 和 172.16.x.x 到 172.31.x.x)并取第一个有效的IP。
- 如果以上都未能找到IP地址,则退回到
REMOTE_ADDR
,它通常是直接连接到服务器的客户端IP。
这种方法能处理多种可能的情况,确保获得最准确的客户端IP地址。