30 题: 如何在PHP中获取客户端IP地址

在...创建的问题 Wed, Feb 13, 2019 12:00 AM

如何使用PHP获取客户端IP地址?

我想记录通过他/她的IP地址登录我网站的用户。

    
1087
  1. 有关记录内容的建议,请参阅RFC6302,特别是现在请记住记录端口而不仅是地址。
    2018-01-03 20:05:19Z
  2. 在全球多个地区,跟踪用户的注意事项ISPS正在使用CGNAT,这使得信任纯粹的IP地址变得更加复杂
    2018-08-08 15:13:00Z
  3. 醇>
    30答案                              30 跨度>                         

    无论您做什么,请确保不要信任从客户端发送的数据。 $_SERVER['REMOTE_ADDR']包含连接方的真实IP地址。这是您可以找到的最可靠的价值。

    但是,它们可能位于代理服务器后面,在这种情况下,代理可能已设置$_SERVER['HTTP_X_FORWARDED_FOR'],但此值很容易被欺骗。例如,它可以由没有代理的人设置,或者IP可以是来自代理后面的LAN的内部IP。

    这意味着如果您要保存$_SERVER['HTTP_X_FORWARDED_FOR'],请确保保存$_SERVER['REMOTE_ADDR']值。例如。将这两个值保存在数据库的不同字段中。

    如果要以字符串形式将IP保存到数据库,请确保至少有 45个字符的空间。 IPv6 将保留,并且这些地址大于旧的IPv4地址。

    (请注意,IPv6通常最多使用39个字符,但也有一个特殊的 IPv6表示法对于IPv4地址,其完整形式最多可包含45个字符。因此,如果您知道自己在做什么,则可以使用39个字符,但如果您只想设置并忘记它,请使用45)。

        
    1245
    2013-11-21 20:51:58Z
    1. 很好的答案!我已经在我的服务器上使用$_SERVER ['REMOTE_ADDR'],我喜欢你包含另一种方式,以及优点和缺点。
      2014-12-22 21:46:02Z
    2. 注意: REMOTE_ADDR可能包含TCP连接的真实IP。这完全取决于您的SAPI。确保正确配置SAPI,以便$_SERVER['REMOTE_ADDR']实际返回TCP连接的IP。如果失败可能会导致一些严重的漏洞,例如,StackExchange用于通过检查REMOTE_ADDR来判断它是否与“localhost”匹配来授予管理员访问权限,不幸的是SAPI的配置........ .................................................. .................
      2015-06-29 04:26:22Z
    3. ................................... ........................................有一个漏洞(需要HTTP_X_FORWARDED_FOR作为输入)允许非管理员通过更改HTTP_X_FORWARDED_FOR标头获得管理员访问权限。另请参阅 blog.ircmaxell.com/2012/11 /解剖的攻击-如何-I-hacked.html
      2015-06-29 04:26:32Z
    4. 什么是$_SERVER['HTTP_CLIENT_IP'])
      2015-11-21 14:28:24Z
    5. @ chiragpatel是的,确实如此。否则,您的服务器配置非常破坏。
      2016-11-11 11:22:33Z
    6. 醇>

    $_SERVER['REMOTE_ADDR']实际上可能不包含真实的客户端IP地址,因为它将为您提供通过代理连接的客户端的代理地址。那可能 不过,这取决于你对IP的影响。如果您说,尝试查看您的流量源自哪里,或者记住用户上次连接的IP,代理或NAT网关的公共IP可能更多,那么某人的私有RFC1918地址可能对您没有任何帮助。适合存放。

    有多个HTTP标头,如X-Forwarded-For,可能会或可能不会由各种代理设置。问题是那些只是HTTP标头,任何人都可以设置。他们的内容无法保证。 $_SERVER['REMOTE_ADDR']是Web服务器从其接收连接并将响应发送到的实际物理IP地址。其他任何事情都只是随意和自愿的信息。只有一种情况可以信任此信息:您正在控制设置此标头的代理。只有当你知道100%在哪里以及如何设置标题时才有意义,你应该注意它的重要性。

    话虽如此,这里有一些示例代码:

     
    if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
        $ip = $_SERVER['HTTP_CLIENT_IP'];
    } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
    } else {
        $ip = $_SERVER['REMOTE_ADDR'];
    }
    

    编者注:使用上述代码有安全隐患。客户端可以将所有HTTP头信息(即$_SERVER['HTTP_...)设置为它想要的任意值。因此,使用$_SERVER['REMOTE_ADDR']更加可靠,因为这不能由用户设置。

    来自: http://roshanbh。 com.np/2007/12/getting-real-ip-address-in-php.html

        
    409
    2016-01-14 12:47:02Z
    1. 除非你完全知道它的作用,否则不要使用上面的代码!由于这个原因,我看到了MASSIVE安全漏洞。客户端可以将X-Forwarded-ForClient-IP标头设置为它想要的任意值。除非您有可信的反向代理,否则不应使用任何这些值。
      2013-06-25 14:37:28Z
    2. 关于Janoszen的评论,一个选项是PHP的filter_var($_ SERVER ['REMOTE_ADDR'],FILTER_VALIDATE_IP)。
      2014-01-27 21:28:42Z
    3. X-Forwarded-For可能包含多个IP地址,以逗号分隔;并且应该真正“解析”而不是采用面值(AFAIK,它几乎从不包含单个IP)。
      2014-02-13 14:51:28Z
    4. @ lostphilosopher这是一个合理的事情,它会使它更可靠,但不幸的是它仍然允许欺骗。
      2014-04-16 08:14:19Z
    5. 对于缩放大小的站点,Web应用程序服务器前面将有负载平衡器和/或反向代理。您必须配置这些负载平衡器或代理以删除任何外部X-Forwarded-For标头,而是插入他们自己的连接客户端所看到的IP地址。
      2014-12-01 06:31:28Z
    6. 醇>
     
    echo $_SERVER['REMOTE_ADDR'];
    

    http://php.net/manual/en/reserved.variables。 server.php

        
    196
    2010-06-09 04:51:31Z
    1. @ Anup Prakash这就是它 - 因此是“REMOTE”(从剧本的角度来看)。
      2010-06-09 05:01:50Z
    2. 我知道了我用你的代码:::1
      2013-10-04 14:09:05Z
    3. 因为你在localhost上;)
      2013-10-08 08:33:17Z
    4. @ SiKni8 ::1是相当于127.0.0.1的IPv6
      2013-12-30 00:17:03Z
    5. @ CamiloMartin你刚刚教我一些东西。爽!
      2015-10-17 03:25:59Z
    6. 醇>

    以下是获取用户IP地址的好方法的清洁代码示例。

     
    $ip = $_SERVER['HTTP_CLIENT_IP'] ? $_SERVER['HTTP_CLIENT_IP'] : ($_SERVER['HTTP_X_FORWARDED_FOR'] ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR']);
    

    以下是使用elvis运算符的较短版本:

     
    $_SERVER['HTTP_CLIENT_IP'] ? : ($_SERVER['HTTP_X_FORWARDED_FOR'] ? : $_SERVER['REMOTE_ADDR']);
    

    这是一个使用isset删除通知的版本(谢谢你,@ shasi kanth):

     
    $ip = isset($_SERVER['HTTP_CLIENT_IP']) ? $_SERVER['HTTP_CLIENT_IP'] : isset($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR'];
    
        
    113
    2019-03-02 23:38:16Z
    1. 始终记得清理用户可能修改过的任何输入。这是其中一次。
      2014-11-25 03:50:11Z
    2. 我相信代码缺少一些表达式并且优先级的顺序是反转的,所以它应该是这样的:$ip = $_SERVER['HTTP_CLIENT_IP']?$_SERVER['HTTP_CLIENT_IP']:($_SERVER['HTTP_X_FORWARDED_FOR']?$_SERVER['HTTP_X_FORWARDED_FOR']:$_SERVER['REMOTE_ADDR']);然而,非常好的。
      2016-06-23 23:11:03Z
    3. 好抓。我调整了帖子。谢谢!
      2016-06-27 20:51:04Z
    4. 刚添加了isset()以删除通知: $ip = isset($_ SERVER ['HTTP_CLIENT_IP'])?$_ SERVER ['HTTP_CLIENT_IP']:isset ($_SERVER [ 'HTTP_X_FORWARDE D_FOR'])$_ SERVER [ 'HTTP_X_FORWARDED_FOR']:$_ SERVER [ 'REMOTE_ADDR'];
      2017-11-29 12:18:04Z
    5. 正如某人所指出的,所有三个例子都是隐藏字符(U + 200C和U + 200B)。不要将它们粘贴到您的PHP脚本中,否则您将获得PARSE ERRORS。如果要查看所有隐藏的字符,请在此处粘贴这些行: soscisurvey.de/tools /view-chars.php 。请清理该代码!
      2018-02-19 11:46:03Z
    6. 醇>

    它应该包含在$_SERVER['REMOTE_ADDR']变量中。

        
    85
    2013-03-07 07:55:37Z

    我最喜欢的解决方案是Zend Framework 2使用的方式。它还考虑$_SERVER属性HTTP_X_FORWARDED_FOR,HTTP_CLIENT_IP,REMOTE_ADDR,但它声明了一个类来设置一些可信代理并返回一个IP地址而不是一个数组。我认为这是最接近它的解决方案:

     
    class RemoteAddress
    {
        /**
         * Whether to use proxy addresses or not.
         *
         * As default this setting is disabled - IP address is mostly needed to increase
         * security. HTTP_* are not reliable since can easily be spoofed. It can be enabled
         * just for more flexibility, but if user uses proxy to connect to trusted services
         * it's his/her own risk, only reliable field for IP address is $_SERVER['REMOTE_ADDR'].
         *
         * @var bool
         */
        protected $useProxy = false;
    
        /**
         * List of trusted proxy IP addresses
         *
         * @var array
         */
        protected $trustedProxies = array();
    
        /**
         * HTTP header to introspect for proxies
         *
         * @var string
         */
        protected $proxyHeader = 'HTTP_X_FORWARDED_FOR';
    
        // [...]
    
        /**
         * Returns client IP address.
         *
         * @return string IP address.
         */
        public function getIpAddress()
        {
            $ip = $this->getIpAddressFromProxy();
            if ($ip) {
                return $ip;
            }
    
            // direct IP address
            if (isset($_SERVER['REMOTE_ADDR'])) {
                return $_SERVER['REMOTE_ADDR'];
            }
    
            return '';
        }
    
        /**
         * Attempt to get the IP address for a proxied client
         *
         * @see http://tools.ietf.org/html/draft-ietf-appsawg-http-forwarded-10#section-5.2
         * @return false|string
         */
        protected function getIpAddressFromProxy()
        {
            if (!$this->useProxy
                || (isset($_SERVER['REMOTE_ADDR']) && !in_array($_SERVER['REMOTE_ADDR'], $this->trustedProxies))
            ) {
                return false;
            }
    
            $header = $this->proxyHeader;
            if (!isset($_SERVER[$header]) || empty($_SERVER[$header])) {
                return false;
            }
    
            // Extract IPs
            $ips = explode(',', $_SERVER[$header]);
            // trim, so we can compare against trusted proxies properly
            $ips = array_map('trim', $ips);
            // remove trusted proxy IPs
            $ips = array_diff($ips, $this->trustedProxies);
    
            // Any left?
            if (empty($ips)) {
                return false;
            }
    
            // Since we've removed any known, trusted proxy servers, the right-most
            // address represents the first IP we do not know about -- i.e., we do
            // not know if it is a proxy server, or a client. As such, we treat it
            // as the originating IP.
            // @see http://en.wikipedia.org/wiki/X-Forwarded-For
            $ip = array_pop($ips);
            return $ip;
        }
    
        // [...]
    }
    

    请在此处查看完整代码: https://raw.githubusercontent.com/zendframework/的Zend-HTTP /主/SRC /PhpEnvironment /RemoteAddress.php

        
    50
    2019-03-05 08:47:55Z
    1. 很棒的答案!使用经过生产测试的代码,在这样一个大框架中开发和使用是您可以做的最好的事情之一:)
      2015-01-19 14:19:31Z
    2. 等等zend没有过滤任何东西?我应该看到类似:filter_var($_SERVER ['REMOTE_ADDR'],FILTER_VALIDATE_IP,FILTER_FLAG_IPV4);
      2015-07-19 05:57:05Z
    3. @ Hanoncs你为什么这样做?欺骗远程地址
      非常困难
      2015-08-10 10:37:49Z
    4. @ Hanoncs我认为你必须在获得这个课程后检查它。它不是它逻辑的一部分。它只是从$_SERVER变量获取值,并跳过一些已定义和众所周知的代理服务器。就这样。如果您认为返回值不安全,请检查它或向PHP开发人员报告错误。
      2015-08-10 16:33:13Z
    5. @ algorhythm如何确定知名代理服务器是什么?
      2016-12-10 16:50:36Z
    6. 醇>

    互联网背后有不同类型的用户,因此我们希望从不同的部分捕获IP地址。那些是:

    1。 $_SERVER['REMOTE_ADDR'] - 它包含客户端的真实IP地址。这是您可以从用户那里找到的最可靠的值。

    2。 $_SERVER['REMOTE_HOST'] - 这将获取用户正在查看当前页面的主机名。但是要使此脚本生效,必须配置httpd.conf内部的主机名查找。

    第3。 $_SERVER['HTTP_CLIENT_IP'] - 当用户来自共享的Internet服务时,这将获取IP地址。

    4。 $_SERVER['HTTP_X_FORWARDED_FOR'] - 当他/她在代理后面时,这将从用户那里获取IP地址。

    因此,我们可以使用以下组合功能来获取正在不同位置查看的用户的真实IP地址,

     
    // Function to get the user IP address
    function getUserIP() {
        $ipaddress = '';
        if (isset($_SERVER['HTTP_CLIENT_IP']))
            $ipaddress = $_SERVER['HTTP_CLIENT_IP'];
        else if(isset($_SERVER['HTTP_X_FORWARDED_FOR']))
            $ipaddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
        else if(isset($_SERVER['HTTP_X_FORWARDED']))
            $ipaddress = $_SERVER['HTTP_X_FORWARDED'];
        else if(isset($_SERVER['HTTP_X_CLUSTER_CLIENT_IP']))
            $ipaddress = $_SERVER['HTTP_X_CLUSTER_CLIENT_IP'];
        else if(isset($_SERVER['HTTP_FORWARDED_FOR']))
            $ipaddress = $_SERVER['HTTP_FORWARDED_FOR'];
        else if(isset($_SERVER['HTTP_FORWARDED']))
            $ipaddress = $_SERVER['HTTP_FORWARDED'];
        else if(isset($_SERVER['REMOTE_ADDR']))
            $ipaddress = $_SERVER['REMOTE_ADDR'];
        else
            $ipaddress = 'UNKNOWN';
        return $ipaddress;
    }
    
        
    43
    2019-02-13 16:02:17Z
    1. 真的很容易伪造。通过将Client-ip标头设置为“111.111.111.111”,我刚刚在我自己的网站上尝试使用Requestly Chrome扩展程序。
      2017-08-10 12:50:40Z
    2. 醇>

    以下是我发现的最先进的方法,过去我已经尝试了其他一些方法。确保获取访问者的IP地址是有效的(但请注意,任何黑客都可以轻易伪造IP地址。)

     
    function get_ip_address() {
    
        // Check for shared Internet/ISP IP
        if (!empty($_SERVER['HTTP_CLIENT_IP']) && validate_ip($_SERVER['HTTP_CLIENT_IP'])) {
            return $_SERVER['HTTP_CLIENT_IP'];
        }
    
        // Check for IP addresses passing through proxies
        if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    
            // Check if multiple IP addresses exist in var
            if (strpos($_SERVER['HTTP_X_FORWARDED_FOR'], ',') !== false) {
                $iplist = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
                foreach ($iplist as $ip) {
                    if (validate_ip($ip))
                        return $ip;
                }
            }
            else {
                if (validate_ip($_SERVER['HTTP_X_FORWARDED_FOR']))
                    return $_SERVER['HTTP_X_FORWARDED_FOR'];
            }
        }
        if (!empty($_SERVER['HTTP_X_FORWARDED']) && validate_ip($_SERVER['HTTP_X_FORWARDED']))
            return $_SERVER['HTTP_X_FORWARDED'];
        if (!empty($_SERVER['HTTP_X_CLUSTER_CLIENT_IP']) && validate_ip($_SERVER['HTTP_X_CLUSTER_CLIENT_IP']))
            return $_SERVER['HTTP_X_CLUSTER_CLIENT_IP'];
        if (!empty($_SERVER['HTTP_FORWARDED_FOR']) && validate_ip($_SERVER['HTTP_FORWARDED_FOR']))
            return $_SERVER['HTTP_FORWARDED_FOR'];
        if (!empty($_SERVER['HTTP_FORWARDED']) && validate_ip($_SERVER['HTTP_FORWARDED']))
            return $_SERVER['HTTP_FORWARDED'];
    
        // Return unreliable IP address since all else failed
        return $_SERVER['REMOTE_ADDR'];
    }
    
    /**
     * Ensures an IP address is both a valid IP address and does not fall within
     * a private network range.
     */
    function validate_ip($ip) {
    
        if (strtolower($ip) === 'unknown')
            return false;
    
        // Generate IPv4 network address
        $ip = ip2long($ip);
    
        // If the IP address is set and not equivalent to 255.255.255.255
        if ($ip !== false && $ip !== -1) {
            // Make sure to get unsigned long representation of IP address
            // due to discrepancies between 32 and 64 bit OSes and
            // signed numbers (ints default to signed in PHP)
            $ip = sprintf('%u', $ip);
    
            // Do private network range checking
            if ($ip >= 0 && $ip <= 50331647)
                return false;
            if ($ip >= 167772160 && $ip <= 184549375)
                return false;
            if ($ip >= 2130706432 && $ip <= 2147483647)
                return false;
            if ($ip >= 2851995648 && $ip <= 2852061183)
                return false;
            if ($ip >= 2886729728 && $ip <= 2887778303)
                return false;
            if ($ip >= 3221225984 && $ip <= 3221226239)
                return false;
            if ($ip >= 3232235520 && $ip <= 3232301055)
                return false;
            if ($ip >= 4294967040)
                return false;
        }
        return true;
    }
    
        
    32
    2019-04-01 14:05:41Z
    1. 这是错误的。 HTTP_CLIENT_IP比REMOTE_ADDR更不可靠,ip验证功能是无意义的。
      2016-01-29 00:59:52Z
    2. @ tobltobs。有趣的是你说这个,但这是唯一一个在重定向页面加载时在一个清漆盒后面为我工作的功能集。我赞不绝口。
      2017-08-31 01:19:10Z
    3. 链接被(有效)破坏。
      2019-03-02 23:32:22Z
    4. 链接被删除,似乎页面消失了。谢谢
      2019-04-29 14:10:47Z
    5. 这是2019年获取IP的最佳方法吗?
      2019-05-03 20:47:41Z
    6. 醇>

    答案是使用 $_SERVER 变量。例如,$_SERVER["REMOTE_ADDR"]将返回客户端的IP地址。

        
    28
    2013-12-17 04:58:25Z

    正如所有其他人所说,您可以使用$_SERVER['REMOTE_ADDR'];获取客户端IP地址。

    此外,如果您需要有关用户的更多信息,可以使用:

     
    <?php
        $ip = '0.0.0.0';
        $ip = $_SERVER['REMOTE_ADDR'];
        $clientDetails = json_decode(file_get_contents("http://ipinfo.io/$ip/json"));
        echo "You're logged in from: <b>" . $clientDetails->country . "</b>";
    ?>
    

    客户端更具体的信息在$clientDetails中。点击 您可以通过以下方式获取存储在$clientDetails变量中的JSON项:$clientDetails-&gt; PostalCode /hostname /region /loc ...

    我正在使用 ipinfo.io 获取更多信息。

        
    10
    2019-02-13 16:06:49Z

    这是我使用的方法,它验证了 IPv4 输入:

     
    // Get user IP address
    if ( isset($_SERVER['HTTP_CLIENT_IP']) && ! empty($_SERVER['HTTP_CLIENT_IP'])) {
        $ip = $_SERVER['HTTP_CLIENT_IP'];
    } elseif ( isset($_SERVER['HTTP_X_FORWARDED_FOR']) && ! empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
    } else {
        $ip = (isset($_SERVER['REMOTE_ADDR'])) ? $_SERVER['REMOTE_ADDR'] : '0.0.0.0';
    }
    
    $ip = filter_var($ip, FILTER_VALIDATE_IP);
    $ip = ($ip === false) ? '0.0.0.0' : $ip;
    
        
    9
    2014-04-09 17:35:52Z
    1. 感谢您允许我通过简单地设置HTTP标头来欺骗我的IP地址!
      2014-04-27 06:21:11Z
    2. 醇>
     
    $ip = "";
    
    if (!empty($_SERVER["HTTP_CLIENT_IP"]))
    {
        // Check for IP address from shared Internet
        $ip = $_SERVER["HTTP_CLIENT_IP"];
    }
    elseif (!empty($_SERVER["HTTP_X_FORWARDED_FOR"]))
    {
        // Check for the proxy user
        $ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
    }
    else
    {
        $ip = $_SERVER["REMOTE_ADDR"];
    }
    echo $ip;
    
        
    9
    2019-02-13 16:12:05Z
    1. 第一个片段如何返回客户端的IP地址?在我看来,它将回显服务器的地址。
      2016-01-08 14:29:01Z
    2. 谢谢罗宾。是的,有时你不会得到正确的结果。请使用第二种解决方案。
      2016-01-10 05:36:40Z
    3. @ MahfuzAhmed,你能说出来,file_get_contents()做了什么?以及如何通过file_get_contents()
      获取IP
      2016-01-18 10:20:33Z
    4. file_get_contents在这里完全没用:)
      2016-01-18 14:09:13Z
    5. 需要在第1行初始化$ip.如果所有条件都失败,那么$ip = $_SERVER['REMOTE_ADDR']也会运行。
      2016-04-08 12:10:19Z
    6. 醇>

    我喜欢这个codesnippet:

     
    function getClientIP() {
    
        if (isset($_SERVER)) {
    
            if (isset($_SERVER["HTTP_X_FORWARDED_FOR"]))
                return $_SERVER["HTTP_X_FORWARDED_FOR"];
    
            if (isset($_SERVER["HTTP_CLIENT_IP"]))
                return $_SERVER["HTTP_CLIENT_IP"];
    
            return $_SERVER["REMOTE_ADDR"];
        }
    
        if (getenv('HTTP_X_FORWARDED_FOR'))
            return getenv('HTTP_X_FORWARDED_FOR');
    
        if (getenv('HTTP_CLIENT_IP'))
            return getenv('HTTP_CLIENT_IP');
    
        return getenv('REMOTE_ADDR');
    }
    
        
    8
    2014-04-09 17:34:39Z
    1. 我的意思是重点...不是getenv给你的东西和$_SERVER一样吗?
      2011-10-02 02:23:44Z
    2. @ Paceriermy猜测是PHP的旧版本,其中$_SERVER尚未可用;)
      2015-01-08 18:55:06Z
    3. @ Johan为什么不直接返回一个包含所有三个数组的数组?
      2016-12-10 16:39:42Z 四>
    4. @ nueverest因为用户不能从3个不同的IP(通常)访问您的站点。您想要返回适用于他的那个。
      2016-12-17 21:07:47Z
    5. 醇>

    试试这个:

     
     $_SERVER['REMOTE_ADDR'];
    
        
    8
    2019-02-13 16:12:40Z
    1. 这已经提到了几次,你回答的实际上并没有任何有用的东西。
      2015-05-26 11:23:38Z
    2. '你回答实际上并没有任何有用的东西' - 不确定你的意思,它回答了被问到的问题。这怎么没用?
      2015-09-10 13:40:10Z
    3. 因为他回答了5年前的问题而且已经回答了很多相同且更好的答案。
      2015-10-12 14:29:42Z
    4. @ gyanendra-prasad-panigrahi尝试在您的答案中包含函数文档等有用的链接。
      2016-05-16 06:49:34Z
    5. 醇>

    嗯,这可以通过使用名为GLOBAL$_SERVER变量来完成。

    $_SERVER是一个属性名称为REMOTE_ADDR的数组。

    只需像这样分配:

     
    $userIp = $_SERVER['REMOTE_ADDR'];
    

    或者像echo $_SERVER['REMOTE_ADDR'];一样直接使用它 或echo ($_SERVER['REMOTE_ADDR']);

        
    7
    2019-02-13 16:10:56Z

    此功能紧凑,您可以随处使用。但是!

    别忘了这个!在这种类型的功能或代码块中,不能保证记录用户的真实IP地址,因为某些用户可以使用代理或其他安全网关来隐藏或无法跟踪

    PHP函数:

     
    function GetIP()
    {
        if ( getenv("HTTP_CLIENT_IP") ) {
            $ip = getenv("HTTP_CLIENT_IP");
        } elseif ( getenv("HTTP_X_FORWARDED_FOR") ) {
            $ip = getenv("HTTP_X_FORWARDED_FOR");
            if ( strstr($ip, ',') ) {
                $tmp = explode(',', $ip);
                $ip = trim($tmp[0]);
            }
        } else {
            $ip = getenv("REMOTE_ADDR");
        }
        return $ip;
    }
    

    用法:

    $IP = GetIP();或直接GetIP();

        
    4
    2019-02-13 16:05:12Z

    以下函数确定所有可能性并以逗号分隔格式(ip,ip等)返回值。

    它还有一个可选的验证功能(默认情况下禁用的第一个参数),用于验证IP地址(私有范围和保留范围)。

     
    <?php
    echo GetClientIP(true);
    
    function GetClientIP($validate = False) {
      $ipkeys = array(
      'REMOTE_ADDR',
      'HTTP_CLIENT_IP',
      'HTTP_X_FORWARDED_FOR',
      'HTTP_X_FORWARDED',
      'HTTP_FORWARDED_FOR',
      'HTTP_FORWARDED',
      'HTTP_X_CLUSTER_CLIENT_IP'
      );
    
      /*
      Now we check each key against $_SERVER if containing such value
      */
      $ip = array();
      foreach ($ipkeys as $keyword) {
        if (isset($_SERVER[$keyword])) {
          if ($validate) {
            if (ValidatePublicIP($_SERVER[$keyword])) {
              $ip[] = $_SERVER[$keyword];
            }
          }
          else{
            $ip[] = $_SERVER[$keyword];
          }
        }
      }
    
      $ip = ( empty($ip) ? 'Unknown' : implode(", ", $ip) );
      return $ip;
    }
    
    function ValidatePublicIP($ip){
      if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
        return true;
      }
      else {
        return false;
      }
    }
    
        
    4
    2019-02-13 16:10:02Z

    用于获取IP地址的安全和警告感知代码段:

     
    $ip = filter_input(INPUT_SERVER, 'HTTP_CLIENT_IP', FILTER_VALIDATE_IP)
        ?: filter_input(INPUT_SERVER, 'HTTP_X_FORWARDED_FOR', FILTER_VALIDATE_IP)
        ?: $_SERVER['REMOTE_ADDR']
        ?? '0.0.0.0'; // Or other value fits "not defined" in your logic
    
        
    3
    2019-02-13 15:58:47Z
     
    function get_client_ip() 
    {
       $ipaddress = '';
        if (getenv('HTTP_CLIENT_IP'))
            $ipaddress = getenv('HTTP_CLIENT_IP');
        else if(getenv('HTTP_X_FORWARDED_FOR'))
            $ipaddress = getenv('HTTP_X_FORWARDED_FOR');
        else if(getenv('HTTP_X_FORWARDED'))
            $ipaddress = getenv('HTTP_X_FORWARDED');
        else if(getenv('HTTP_FORWARDED_FOR'))
            $ipaddress = getenv('HTTP_FORWARDED_FOR');
        else if(getenv('HTTP_FORWARDED'))
           $ipaddress = getenv('HTTP_FORWARDED');
        else if(getenv('REMOTE_ADDR'))
            $ipaddress = getenv('REMOTE_ADDR');
        else
            $ipaddress = 'UNKNOWN';
    
       return $ipaddress;
    } 
    
        
    1
    2016-11-26 10:24:10Z

    以下是获取客户端IP地址的单行版本:

      

    $ip = @$_SERVER['HTTP_CLIENT_IP'] ?: @$_SERVER['HTTP_X_FORWARDED_FOR'] ?: @$_SERVER['REMOTE_ADDR'];

    不ES:

    • 通过使用@,它会抑制PHP通知。
    • 来自HTTP_X_FORWARDED_FOR的值可能包含以逗号分隔的多个地址,因此如果您希望获得第一个地址,则可以使用以下方法:

       
      current(explode(',', @$_SERVER['HTTP_X_FORWARDED_FOR']))
      
    1
    2018-03-06 18:52:24Z

    此功能应按预期工作

     
    function Get_User_Ip()
    {
        $IP = false;
        if (getenv('HTTP_CLIENT_IP'))
        {
            $IP = getenv('HTTP_CLIENT_IP');
        }
        else if(getenv('HTTP_X_FORWARDED_FOR'))
        {
            $IP = getenv('HTTP_X_FORWARDED_FOR');
        }
        else if(getenv('HTTP_X_FORWARDED'))
        {
            $IP = getenv('HTTP_X_FORWARDED');
        }
        else if(getenv('HTTP_FORWARDED_FOR'))
        {
            $IP = getenv('HTTP_FORWARDED_FOR');
        }
        else if(getenv('HTTP_FORWARDED'))
        {
            $IP = getenv('HTTP_FORWARDED');
        }
        else if(getenv('REMOTE_ADDR'))
        {
            $IP = getenv('REMOTE_ADDR');
        }
    
        //If HTTP_X_FORWARDED_FOR == server ip
        if((($IP) && ($IP == getenv('SERVER_ADDR')) && (getenv('REMOTE_ADDR')) || (!filter_var($IP, FILTER_VALIDATE_IP))))
        {
            $IP = getenv('REMOTE_ADDR');
        }
    
        if($IP)
        {
            if(!filter_var($IP, FILTER_VALIDATE_IP))
            {
                $IP = false;
            }
        }
        else
        {
            $IP = false;
        }
        return $IP;
    }
    
        
    1
    2019-03-01 06:38:30Z

    其中一个:

     
        $ip = $_SERVER['REMOTE_ADDR'];
        $ip = $_SERVER['HTTP_CLIENT_IP'];
        $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
        $ip = $_SERVER['HTTP_X_FORWARDED'];
        $ip = $_SERVER['HTTP_FORWARDED_FOR'];
        $ip = $_SERVER['HTTP_FORWARDED'];
    
        
    1
    2019-06-11 10:14:08Z

    快速解决方案(无错误)

     
    function getClientIP()
    {
        $ipaddress = 'UNKNOWN';
        $keys=array('HTTP_CLIENT_IP','HTTP_X_FORWARDED_FOR','HTTP_X_FORWARDED','HTTP_FORWARDED_FOR','HTTP_FORWARDED','REMOTE_ADDR');
        foreach($keys as $k)
        {
            if (isset($_SERVER[$k]) && !empty($_SERVER[$k]) && filter_var($_SERVER[$k], FILTER_VALIDATE_IP))
            {
                $ipaddress = $_SERVER[$k];
                break;
            }
        }
        return $ipaddress;
    }
    
        
    1
    2019-06-23 08:04:18Z
    1. 非常感谢Sir!
      2019-06-23 12:10:04Z
    2. 醇>
     
    $_SERVER['REMOTE_ADDR'];
    

    示例:

     
    if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
        $ip = $_SERVER['HTTP_CLIENT_IP'];
    } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
    } else {
        $ip = $_SERVER['REMOTE_ADDR'];
    }
    
        
    0
    2016-05-23 06:15:58Z
    1. 我想知道为什么会有这么多的downvotes。我找到了答案,虽然不是最好的(因为它不考虑内部网络,如负载平衡服务器,非常有用,文档提供了上下文。我想有些人只是想要一个解决方案工作而不用进一步质疑,
      2016-05-22 18:27:39Z
    2. 醇>

    这是一个简单的单线

     
    $ip = $_SERVER['HTTP_X_FORWARDED_FOR']?: $_SERVER['HTTP_CLIENT_IP']?: $_SERVER['REMOTE_ADDR'];
    

    编辑:

    以上代码可能会返回保留地址(如10.0.0.1),途中所有代理服务器的地址列表等。 要处理这些情况,请使用以下代码:

     
    function valid_ip($ip) {
        // for list of reserved IP addresses, see https://en.wikipedia.org/wiki/Reserved_IP_addresses
        return $ip && substr($ip, 0, 4) != '127.' && substr($ip, 0, 4) != '127.' && substr($ip, 0, 3) != '10.' && substr($ip, 0, 2) != '0.' ? $ip : false;
    }
    
    function get_client_ip() {
        // using explode to get only client ip from list of forwarders. see https://en.wikipedia.org/wiki/X-Forwarded-For
        return
        @$_SERVER['HTTP_X_FORWARDED_FOR'] ? explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'], 2)[0] :
        @$_SERVER['HTTP_CLIENT_IP'] ? explode(',', $_SERVER['HTTP_CLIENT_IP'], 2)[0] :
        valid_ip(@$_SERVER['REMOTE_ADDR']) ?:
        'UNKNOWN';
    }
    
    echo get_client_ip();
    
        
    0
    2016-11-17 10:35:35Z

    喜欢以下内容?

     
    if (($ip=filter_input(INPUT_SERVER, 'REMOTE_ADDR', validate_ip)) === false or empty($ip)) {
        exit;
    }
    echo $ip;
    

    PS

     
    if (($ip=filter_input(INPUT_SERVER, 'REMOTE_ADDR', FILTER_VALIDATE_IP|FILTER_FLAG_NO_PRIV_RANGE|FILTER_FLAG_NO_RES_RANGE)) === false) {
        header('HTTP/1.0 400 Bad Request');
        exit;
    }
    

    以“HTTP_”或“X-”开头的所有标题可能都是欺骗性的,分别是用户定义的。如果你想跟踪,使用cookies等

        
    0
    2019-03-02 23:35:01Z
     
    // Function to get the client ip address
    function get_ip() 
    {
    
    if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
        $ip = $_SERVER['HTTP_CLIENT_IP'];
    } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
    } else {
        $ip = $_SERVER['REMOTE_ADDR'];
    }
    return $ip;
    
    
    }
    
        
    0
    2019-04-01 07:42:14Z

    就这一点而言,我很惊讶它尚未被提及,是为了获得那些位于CloudFlare基础设施之后的网站的正确IP地址。它将破坏您的IP地址,并为它们提供相同的价值。 幸运的是,他们也有一些服务器头。 而不是我重写已经写的东西,看看h我想要一个更简洁的答案,是的,我很久以前也经历过这个过程。 https://stackoverflow.com/a/14985633/1190051

        
    0
    2019-04-29 04:51:14Z
     
    function get_client_ip()
    {
        foreach (array(
                    'HTTP_CLIENT_IP',
                    'HTTP_X_FORWARDED_FOR',
                    'HTTP_X_FORWARDED',
                    'HTTP_X_CLUSTER_CLIENT_IP',
                    'HTTP_FORWARDED_FOR',
                    'HTTP_FORWARDED',
                    'REMOTE_ADDR') as $key) {
            if (array_key_exists($key, $_SERVER)) {
                foreach (explode(',', $_SERVER[$key]) as $ip) {
                    $ip = trim($ip);
                    if ((bool) filter_var($ip, FILTER_VALIDATE_IP,
                                    FILTER_FLAG_IPV4 |
                                    FILTER_FLAG_NO_PRIV_RANGE |
                                    FILTER_FLAG_NO_RES_RANGE)) {
                        return $ip;
                    }
                }
            }
        }
        return null;
    }
    

    或压缩版本:

     
    function get_ip() {
        foreach (array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR') as $key) {
            if (array_key_exists($key, $_SERVER) === true) {
                foreach (array_map('trim', explode(',', $_SERVER[$key])) as $ip) {
                    if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false) {
                        return $ip;
                    }
                }
            }
        }
    }
    
    
        
    0
    2019-05-20 13:58:15Z

    这里有一些代码应该通过各种来源选择有效的IP检查。

    首先,它检查'REMOTE_ADDR'是否是公共IP(而不是您的一个可信反向代理),然后通过其中一个HTTP标头,直到它找到公共IP并返回它。 (PHP 5.2 +)

    只要反向代理可信或服务器与客户端直接连接,它就应该可靠。

     
    //Get client's IP or null if nothing looks valid
    function ip_get($allow_private = false)
    {
      //Place your trusted proxy server IPs here.
      $proxy_ip = ['127.0.0.1'];
    
      //The header to look for (Make sure to pick the one that your trusted reverse proxy is sending or else you can get spoofed)
      $header = 'HTTP_X_FORWARDED_FOR'; //HTTP_CLIENT_IP, HTTP_X_FORWARDED, HTTP_FORWARDED_FOR, HTTP_FORWARDED
    
      //If 'REMOTE_ADDR' seems to be a valid client IP, use it.
      if(ip_check($_SERVER['REMOTE_ADDR'], $allow_private, $proxy_ip)) return $_SERVER['REMOTE_ADDR'];
    
      if(isset($_SERVER[$header]))
      {
        //Split comma separated values [1] in the header and traverse the proxy chain backwards.
        //[1] https://en.wikipedia.org/wiki/X-Forwarded-For#Format
        $chain = array_reverse(preg_split('/\s*,\s*/', $_SERVER[$header]));
        foreach($chain as $ip) if(ip_check($ip, $allow_private, $proxy_ip)) return $ip;
      }
    
       return null;
    }
    
    //Check for valid IP. If 'allow_private' flag is set to truthy, it allows private IP ranges as valid client IP as well. (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
    //Pass your trusted reverse proxy IPs as $proxy_ip to exclude them from being valid.
    function ip_check($ip, $allow_private = false, $proxy_ip = [])
    {
      if(!is_string($ip) || is_array($proxy_ip) && in_array($ip, $proxy_ip)) return false;
      $filter_flag = FILTER_FLAG_NO_RES_RANGE;
    
      if(!$allow_private)
      {
        //Disallow loopback IP range which doesn't get filtered via 'FILTER_FLAG_NO_PRIV_RANGE' [1]
        //[1] https://www.php.net/manual/en/filter.filters.validate.php
        if(preg_match('/^127\.$/', $ip)) return false;
        $filter_flag |= FILTER_FLAG_NO_PRIV_RANGE;
      }
    
      return filter_var($ip, FILTER_VALIDATE_IP, $filter_flag) !== false;
    }
    
        
    0
    2019-06-02 07:12:47Z
来源放置 这里