【问题标题】:How to code feature on checking visitor IP address in PHP?如何在 PHP 中编写检查访问者 IP 地址的功能?
【发布时间】:2011-01-31 03:11:03
【问题描述】:

我仍然对这个问题感到困惑,并寻求有关如何通过 PHP 检查访问者 IP 地址的任何帮助和参考。

我知道在尝试编写要显示的代码之前询问某些内容似乎很懒惰,但现在,我也在谷歌上搜索它。希望有人可以给出一般性的广泛答案或一些阅读链接?

顺便说一句,当我们必须编写这样的一些功能时要考虑什么?

PS:非常感谢大家。这是有启发性的论点。坦率地说,我选择答案更多的是尊重而不是其中的真相。因为直到现在我仍然不知道正确的那个。也许我需要更多年的学习才能对主题本身有深刻的理解。

【问题讨论】:

  • @Mike 最好不要链接该代码。
  • @Col 因为...?无论接受的答案如何,我们是否可以同意实际问题几乎相同?
  • 因为每个点赞的人都不知道。任何仅返回一个 IP 地址且此地址不是 REMOTE_ADDR 的代码都是错误的。因为 PHP 拥有的唯一 IP 地址(根据 TCP/IP 协议)是 REMOTE_ADDR。其余的只是 HTTP 标头

标签: php proxy ip-address


【解决方案1】:

如果您的客户端通过代理服务器上网,那么$_SERVER['REMOTE_ADDR'] 只会返回代理服务器的 IP 地址,而不是客户端机器的 IP 地址。这不是很可靠。这可能是一个更好的解决方案:

function get_ip_address() {
 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); // just to be safe
    if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false) {
     self::$ip = $ip;
     return $ip;
    }
   }
  }
 }
}

这已经在 Stack Overflow 上讨论过了。请参考“What is the most accurate way to retrieve a user’s correct IP address in PHP?”。上面的代码是对该问题的公认答案的优化版本。

但是,请注意获取 IP 地址永远不会完全可靠:php / ajax REMOTE_ADDR set to IP of bogus network adapter

【讨论】:

  • @Col 称代码愚蠢并说它没有回答问题是两件截然不同的事情。
  • @Mathias 1. 像 HTTP 标头一样简单地欺骗 IP 地址。 2. IP 地址总是比 HTTP 头更可靠。 3. 这段代码尝试失败。
  • @Col 你可以用多少种方式改写同一件事?我要你解释为什么不建议使用 REMOTE_ADDR 以外的任何东西,而你似乎只是简单的侮辱。我不是要开始一场宗教争论。我相信你有一个很好的理由。我只是想知道它是什么。
  • @Mike 我已经说过很多次了。 PHP 拥有的唯一 IP 地址(根据 TCP/IP 协议)是 REMOTE_ADDR。其余的只是 HTTP 标头。
  • 插话...REMOTE_ADDR不可欺骗的。这是 TCP/IP 协议在三次握手中确认的地址,以便建立双向连接,因此您的服务器可以将某些内容发送回客户端。 HTTP 标头 OTOH 由客户端设置,可以是任何东西。此外,您的业务是在代理背后寻找什么,您可以获得什么?可能是一堆10.0.1.x 地址,对你也没有多大帮助。
【解决方案2】:

$_SERVER,具体来说:

$_SERVER['REMOTE_ADDR'];

【讨论】:

  • 如果您的客户端通过代理服务器上网,那么$_SERVER['REMOTE_ADDR'] 只返回代理服务器的 IP 地址,而不是客户端机器的 IP 地址。这不是很可靠。这可能是一个更好的解决方案:stackoverflow.com/questions/2505697/… 但是,请注意获取 IP 地址永远不会完全可靠:stackoverflow.com/questions/1672827/…
  • @Mathais Bynens:与您可能尝试检测的任何 HTTP 标头一样或更可靠。而且它不需要大量代码。
【解决方案3】:

一般性的广泛回答:PHP 所知道的关于客户端的所有信息都存储在 $_SERVER 变量中。 因此,每次您需要特定信息时都执行此代码,以查看是否可以找到相关信息:

echo "<pre>";
print_r($_SERVER);
echo "</pre>";
//or just
phpinfo(32);

$_SERVER['REMOTE_ADDR'] 是您可以获得的唯一IP 地址,但它不能是“客户端地址”。

【讨论】:

    【解决方案4】:

    要获取用户 IP 地址,您应该使用它,

    $ip = $_SERVER['REMOTE_ADDR']
    

    【讨论】:

    • 如果您的客户端通过代理服务器上网,那么$_SERVER['REMOTE_ADDR'] 只返回代理服务器的 IP 地址,而不是客户端机器的 IP 地址。这不是很可靠。这可能是一个更好的解决方案:stackoverflow.com/questions/2505697/… 但是,请注意获取 IP 地址永远不会完全可靠:stackoverflow.com/questions/1672827/…
    • @Mathias 好吧,你最后能决定哪个“不太可靠”吗? HTTP 标头如何比 IP 地址更可靠?
    • 当用户使用代理服务器时,您会在此找到您的分析器。 function getRealIpAddr() { if (!empty($_SERVER['HTTP_CLIENT_IP'])) //从共享互联网检查 ip { $ip=$_SERVER['HTTP_CLIENT_IP']; } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) //检查 ip 是否从代理传递 { $ip=$_SERVER['HTTP_X_FORWARDED_FOR']; } 其他 { $ip=$_SERVER['REMOTE_ADDR']; } 返回 $ip;该函数首先尝试获取客户端机器的直接IP地址,如果不可用则尝试使用HTTP_X_FORWARDED_FOR转发IP地址。
    • 这不是您选择的 IP 地址,而是 HTTP 标头。
    【解决方案5】:

    以下内容将达到目的。

    $ip = $_SERVER['REMOTE_ADDR'];
    
    echo "IP address is : " :.$ip;
    

    【讨论】:

      【解决方案6】:

      我建议您使用第三方 IP 地址到地理转换器来计算位置。由于您不必裸露数据库空间..准确性和查询。

      你需要做的就是像

      http://third-party-url.com?ip=IP_ADDRESS
      

      它会返回 XML 或数据数组。

      以后你可以用它来做任何你想做的事情。

      这里有两个很受欢迎的网站。 * My IP Address Lookup and GeoTargeting * SimpleGeo

      这样的网站很多..也许其他人可以在这里添加它们。

      【讨论】:

        【解决方案7】:

        好的,justjoe,我知道你对这个争论感到困惑,我在其中很重要。

        给你一些解释。

        答案取决于任务。你有两个选择:

        如果您只需要一个 IP 地址,则可以只使用 REMOTE_ADDR 而不使用其他地址。看一下网络服务器的访问日志:只有一个 IP 地址,它是 REMOTE_ADDR 一个。至少它保证了您的 IP 地址有效。在许多情况下,就像流量计数器一样,它是您唯一可以依赖的东西。这是对“如何获取 IP 地址”问题的一般回答。

        如果您想记录一个可能更精确的地址 - 因此,没有人会禁止您记录多个地址,而不是一个。但是,当然,您必须将这些 HTTP 标头与 REMOTE_ADDR 一起记录,而不是代替它。这样一大堆地址是有一些用处的。但是你不能过分依赖它。但是你可以从中挖掘一些信息,如果你在乎的话。

        FORWARDED_FOR 标头的唯一情况是网络服务器配置错误,它将真实 IP 地址放入此变量中。在这种情况下,它可以用作 IP 地址。但当然,它必须在每个特定情况下手动完成,而不是作为一般建议。但无论如何,我会退出这样的网络服务器,因为其中不可能只有一个错误配置。

        【讨论】:

        • 非常感谢您的解释。现在我明白了创建此类功能时要考虑的事项。我用它来跟踪用户。虽然关于 ip 的范围,我想我只需要一个。拥有正确的ip很重要。但是代码不是必须拥有真实的Everyhing 将存储在数据库中。它更像是手动黑名单/白名单功能。
        • 我正在测试使用 xampp 在我的本地 php 开发环境中获取引荐网站 IP 地址,但此代码没有显示 IP - var_dump("ip=".$_SERVER['REMOTE_ADDR']);但是这段代码显示了它 - var_dump(gethostbyname("site address here pass"));那么哪种方法是正确的呢?
        • @devm 引用站点与 IP 地址完全无关。该地址不属于网站,而是属于网站访问者
        【解决方案8】:

        只需在代码顶部使用它:

        if (function_exists('apache_request_headers'))
        {
            $headers = apache_request_headers();
        
            if (array_key_exists('X-Forwarded-For', $headers))
            {
                $ips = explode(',',$headers['X-Forwarded-For'],2);
                $_SERVER["REMOTE_ADDR"]= trim($ips[0]);
            }
        }
        

        它将确保$_SERVER["REMOTE_ADDR"] 始终在负载平衡器应用程序上保持正确的 IP 地址。

        【讨论】:

        • 并始终保留错误的 IP,以防根本没有配置错误的负载均衡器。
        • 如果有 X-Forwarded-For 那么你怎么可能配置错误的负载均衡器?另外,如果你担心这样的事情,你也不会使用负载均衡器,这意味着上面的代码赢了无论如何都不适用于你......
        • 因为 X-Forwarded-For 不是您可能认为的负载均衡器专有功能。但只是非常常见的 HTTP 标头,可以由任何代理或路由器添加。
        猜你喜欢
        • 2023-03-31
        • 2011-12-17
        • 2020-12-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多