1.前言
PHP如何获取用户的真实IP地址?如果看过一些入门教科书的朋友可能会记得,书上告诉我们使用如下方法获取:$_SERVER["REMOTE_ADDR"];但是现实真的是如此吗?并不是,因为随着互联网的发展,我们访问的途径变得多种多样,用户可以使用代理IP代理访问、也可能通过CDN加速访问,那么你所获取的IP可能只是代理或者最近一个节点的IP,而不是真实用户的IP。
2.打印服务器在不同状态下的捕捉情况
根据下面的代码,我们可以得到各个CDN加速后的IP结果:
<?php
print_r($_SERVER);
?>
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 是什么?不然看的一脸懵逼。
- REMOTE_ADDR 表示访客 IP ,如果使用代理访问则显示代理 IP
- HTTP_X_FORWARDED_FOR 表示访客 IP ,如果不使用代理访问则为空
- HTTP_CLIENT_IP 表示代理服务器 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 。
来源:oschina
链接:https://my.oschina.net/mtdg/blog/4330377