PHP获取用户真实IP的正确姿势

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_ADDRHTTP_X_FORWARDED_FORHTTP_CLIENT_IP

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章