zoukankan      html  css  js  c++  java
  • PHP 获取客户端ip地址

    一、如果没有使用代理服务器,

    REMOTE_ADDR= 客户端IP HTTP_X_FORWARDED_FOR= 没数值或不显示

    $ip = $_SERVER['REMOTE_ADDR'];
    

    二、使用透明代理,

    REMOTE_ADDR= 最后一个代理服务器 IP
    HTTP_X_FORWARDED_FOR= 客户端真实 IP (经过多个代理服务器时,这个值类似:221.5.252.160, 203.98.182.163, 203.129.72.215)

    这类代理还会将客户真实ip发送到请求对象,无法隐藏真实ip。

    $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
    

    三、使用普通匿名代理服务器,

    REMOTE_ADDR= 最后一个代理服务器 IP
    HTTP_X_FORWARDED_FOR = 代理服务器 IP (经过多个代理服务器时,这个值类似:203.98.182.163, 203.98.182.163, 203.129.72.215)

    这样就隐藏了客户端的真实ip,但服务器会知道客户端是通过代理服务器去访问的。

    四、使用欺骗性代理服务器,

    REMOTE_ADDR= 代理服务器 IP
    HTTP_X_FORWARDED_FOR= 随机的 IP(经过多个代理服务器时,这个值类似:220.4.251.159, 203.98.182.163, 203.129.72.215)

    服务器可以识别到时通过代理服务器访问的,但发送给目标服务器的是虚假ip。

    五、使用高匿名代理,

    REMOTE_ADDR= 代理服务器 IP HTTP_X_FORWARDED_FOR= 没数值或不显示

    使用这种代理时,不同浏览器不同设备会返回不同的ip头信息,因此PHP使用$_SERVER["REMOTE_ADDR"]$_SERVER["HTTP_X_FORWARDED_FOR"] 获取的值可能是空值也可能是“unknown”值。

    PHP获取ip代码方法1:

    function getip() {
        static $realip;
        if (isset($_SERVER)) {
            if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
                $realip = $_SERVER['HTTP_X_FORWARDED_FOR'];
            } else if (isset($_SERVER['HTTP_CLIENT_IP'])) {
                $realip = $_SERVER['HTTP_CLIENT_IP'];
            } else {
                $realip = $_SERVER['REMOTE_ADDR'];
            }
        } else {
            if (getenv('HTTP_X_FORWARDED_FOR')) {
                $realip = getenv('HTTP_X_FORWARDED_FOR');
            } else if (getenv('HTTP_CLIENT_IP')) {
                $realip = getenv('HTTP_CLIENT_IP');
            } else {
                $realip = getenv('REMOTE_ADDR');
            }
        }
        return $realip;
    }
    

    PHP获取ip代码方法2:

    function getip(){
        $ip=false;
        if(!empty($_SERVER['HTTP_CLIENT_IP'])){
            $ip=$_SERVER['HTTP_CLIENT_IP'];
        }
        if(!empty($_SERVER['HTTP_X_FORWARDED_FOR'])){
            $ips=explode (', ', $_SERVER['HTTP_X_FORWARDED_FOR']);
            if($ip){
                array_unshift($ips, $ip);
                $ip=FALSE;
            }
            for ($i=0; $i < count($ips); $i++){
                if(!eregi ('^(10│172.16│192.168).', $ips[$i])){
                    $ip=$ips[$i];
                    break;
                }
            }
        }
        return ($ip ? $ip : $_SERVER['REMOTE_ADDR']);
    }
    
    

    根据ip获取归属地信息

    /**
    获取 IP  地理位置
     * 淘宝IP接口
     * @Return: array
     */
    function getCity($ip = '')
    {
        $url="http://ip.taobao.com/service/getIpInfo.php?ip=".$ip;
        $ip=json_decode(file_get_contents($url));
        if((string)$ip->code=='1'){
            return false;
        }
        $data = (array)$ip->data;
        return $data;
    }



    现状

    目前主流的函数方法:

    <?php
    function getIp()
    {
        if ($_SERVER["HTTP_CLIENT_IP"] && strcasecmp($_SERVER["HTTP_CLIENT_IP"], "unknown")) {
            $ip = $_SERVER["HTTP_CLIENT_IP"];
        } else {
            if ($_SERVER["HTTP_X_FORWARDED_FOR"] && strcasecmp($_SERVER["HTTP_X_FORWARDED_FOR"], "unknown")) {
                $ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
            } else {
                if ($_SERVER["REMOTE_ADDR"] && strcasecmp($_SERVER["REMOTE_ADDR"], "unknown")) {
                    $ip = $_SERVER["REMOTE_ADDR"];
                } else {
                    if (isset ($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'],
                            "unknown")
                    ) {
                        $ip = $_SERVER['REMOTE_ADDR'];
                    } else {
                        $ip = "unknown";
                    }
                }
            }
        }
        return ($ip);
    }
    
    echo getIp();
    

    测试

    curl伪造IP请求:

    $ch = curl_init('http://localhost/ip.php');
    
    //通用设置
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);//不直接输出
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);//跟踪重定向
    
    //伪造请求头
    $ip = mt_rand(1, 255) . '.' . mt_rand(1, 255) . '.' . mt_rand(1, 255) . '.' . mt_rand(1, 255);
    $header = [
        'CLIENT-IP: ' . $ip,
        'X-FORWARDED-FOR: ' . $ip,
        'X-REAL-IP: ' . $ip,
        'Accept-Language: zh-CN,zh;',
    ];
    curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
    
    $html = curl_exec($ch);
    curl_close($ch);
    echo $html;
    

    输出SERVER数组,发现【HTTP_CLIENT_IP】、【HTTP_X_FORWARDED_FOR】、【HTTP_X_REAL_IP】是随机变动的IP地址。

    主流方法根本不安全!

    分析

    为什么?

    HTTP_CLIENT_IP:存在于http请求的header
    HTTP_X_FORWARDED_FOR:请求转发路径,客户端IP,代理1IP,代理2IP......
    HTTP_X_REAL_IP:这个用得比较少,暂不讨论。
    

    这三个值都是从HTTP请求头获取的,所以并不可靠!

    REMOTE_ADDR

    REMOTE_ADDR:是直接从TCP中获取的IP,基本不会被伪造!

    返回查看$_SERVER数组,发现【REMOTE_ADDR】显示正确的IP!

    所以直接用 $_SERVER['REMOTE_ADDR'] 就解决问题了?

    其实还不行,如果客户端和服务器之间存在代理服务器,【REMOTE_ADDR】的值是最后一个代理服务器的IP!

    只有第一台接收客户端请求的代理服务器的【REMOTE_ADDR】值才是客户的真实IP地址,要把该值传递下去!

    解决方案

    1. 客户端和服务器直连

    <?php
    function get_client_ip()
    {
        $ip = $_SERVER['REMOTE_ADDR'];
        return $ip;
    }
    

    2. 客户端和服务器存在中间代理

    第一层nginx代理设置:

    proxy_set_header X-Forwarded-For $remote_addr;

    其他层nginx代理设置:

    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    PHP代码:

    <?php
    function get_client_ip()
    {
        $ip = null;
        if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            $ip = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
            $ip = trim(current($ip));
        }
        return $ip;
    }

     另:

    <?php
    function getIP()
    {
    static $realip;
    if (isset($_SERVER)){
    if (isset($_SERVER["HTTP_X_FORWARDED_FOR"])){
    $realip = $_SERVER["HTTP_X_FORWARDED_FOR"];
    } else if (isset($_SERVER["HTTP_CLIENT_IP"])) {
    $realip = $_SERVER["HTTP_CLIENT_IP"];
    } else {
    $realip = $_SERVER["REMOTE_ADDR"];
    }
    } else {
    if (getenv("HTTP_X_FORWARDED_FOR")){
    $realip = getenv("HTTP_X_FORWARDED_FOR");
    } else if (getenv("HTTP_CLIENT_IP")) {
    $realip = getenv("HTTP_CLIENT_IP");
    } else {
    $realip = getenv("REMOTE_ADDR");
    }
    }
    return $realip;
    }

    echo getIP();
    ?>

    简易

    <?php
    $ip = $_SERVER['REMOTE_ADDR'];

    echo $ip;
    ?>

  • 相关阅读:
    记一次小程序支付开发的坑,超级坑
    springboot集成redis 附redis基本操作类
    springboot整合mybatis及封装curd操作-配置文件
    微信小程序开发
    vue各种插件
    java数据导出成 EXCEL
    jsp自定义标签
    java生成验证码
    文字对齐格式
    css阴影效果
  • 原文地址:https://www.cnblogs.com/surplus/p/12285915.html
Copyright © 2011-2022 走看看