精选30+云产品,推动企业轻松上云! >>>
1. 序言
PHP如何获取用户的真实IP地址? 如果你读过一些入门教材php获取真实ip,你可能还记得书上告诉我们用下面的方法来获取:$_SERVER["REMOTE_ADDR"]; 事实真的是这样吗? 不,因为随着互联网的发展php获取真实ip,我们有多种访问方式。 用户可以使用代理IP代理访问,也可能通过CDN加速访问,所以你得到的IP可能只是代理或者最近节点的IP。 ,不是真实用户的IP。
2、复制服务器不同状态下的抓包情况
根据下面的代码,我们可以得到各个CDN加速的IP结果:
2.1 百度CDN复制结果
Array ( [HTTP_X_FORWARDED_FOR] => 119.164.27.53,123.234.0.103,27.221.124.94 [HTTP_X_REAL_IP] => 119.164.27.53 [REMOTE_ADDR] => 150.138.138.169 ......... )
2.2 阿里CDN复制结果
Array ( [HTTP_ALI_CDN_REAL_IP] => 119.164.27.53 [HTTP_X_FORWARDED_FOR] => 119.164.27.53 [REMOTE_ADDR] => 115.124.31.68 ......... )
2.3 七云牛CDN复制结果
Array ( [HTTP_ALI_CDN_REAL_IP] => 119.164.27.53 [HTTP_X_FORWARDED_FOR] => 119.164.27.53 [REMOTE_ADDR] => 182.92.246.161 ......... )
总结几种常见的CDN加速方法,我们可以得出结论,在使用CDN时,$_SERVER变量会富含“HTTP_X_FORWARDED_FOR”元素,而且里面富含用户的真实IP地址,所以根据这个特点,我们可以封装具有以下功能:
function _get_client_ip() { $clientip = ''; if(getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown')) { $clientip = getenv('HTTP_CLIENT_IP'); } elseif(getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), 'unknown')) { $clientip = getenv('HTTP_X_FORWARDED_FOR'); } elseif(getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), 'unknown')) { $clientip = getenv('REMOTE_ADDR'); } elseif(isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown')) { $clientip = $_SERVER['REMOTE_ADDR']; } preg_match("/[d.]{7,15}/", $clientip, $clientipmatches); $clientip = $clientipmatches[0] ? $clientipmatches[0] : 'unknown'; return $clientip; }
首先解释一下什么是REMOTE_ADDR、HTTP_X_FORWARDED_FOR、HTTP_CLIENT_IP? 否则,你会显得很困惑。
PS:REMOTE_ADDR很难修改,而HTTP_X_FORWARDED_FOR、HTTP_CLIENT_IP是客户端(通常指代理服务器)设置的。
3、根据不同需求选择不同的解决方案
对于IP地址的获取和使用,我们应根据业务和需求获取用户的IP地址。
3.1 投票系统/活动
在做投票系统/活动时,最重要的是避免刷票,所以建议使用$_SERVER["REMOTE_ADDR"]来获取客户IP,因为通过HTTP_X_FORWARDED_FOR、HTTP_CLIENT_IP获取的IP可能是被刷卡者伪造的,而 $_SERVER["REMOTE_ADDR"] 是最安全的。
3.2 网站访问统计
这时我们就应该利用我们封装的函数来获取用户的IP地址,这样访问者通过代理服务器访问网站时就可以获取到访问者的真实IP。 如果你觉得网络比较复杂,可以同时存储REMOTE_ADDR、HTTP_X_FORWARDED_FOR和HTTP_CLIENT_IP。