【问题标题】:Retrieve real IP of user using codeigniter使用 codeigniter 检索用户的真实 IP
【发布时间】:2017-11-20 17:23:57
【问题描述】:

我的应用会跟踪登录网站的用户的 IP 地址。跟踪在常规 Web 服务器上运行良好(我们在 hostgator 上),但是当我们切换到 PaaS 平台(pagodabox)时似乎开始跟踪奇怪的 IP 地址 在与 pagodabox 支持人员交谈后,他们告诉我 IPs codeigniter 正在接收是pagodabox 的负载均衡器/路由器的 IP 并获取用户的实际 IP 地址,我必须使用 HTTP_X_FORWARDED_FOR

我正在使用 codeigniter 的输入类函数 $this->input->ip_address() 来检索用户的 IP。我查看了该功能,发现他们有一些功能可以检索HTTP_X_FORWARDED_FOR IP 值,但我不知道如何使用它。我必须在配置中更改/添加一些东西吗?

编辑:在一些用户指出我应该在负载均衡器的 IP 地址列表中添加的位置之后,出现了一个新问题:如果 IP 列表经常更改,我该怎么办? (即没有静态IP,全是动态的)

【问题讨论】:

  • 到最后一个问题,什么意思?如果IP经常更改,那么您将获得更改后的IP。为什么你需要对此做任何事情?
  • @eis pagodabox 在其负载均衡器中不使用静态 IP 它们的 IP 是动态变化的。每次负载均衡器的 IP 更改(可能是每秒一次)时,我都无法更新配置文件
  • 好的。我看起来不像 codeigniter 被设计用于这样的设置。

标签: php codeigniter


【解决方案1】:

我确定您现在已经解决了这个问题,但我想我会发布正确的答案以供将来参考。我遇到了同样的问题(在 AWS 上使用负载均衡器和 CodeIgniter 应用程序。)正如您所指出的,使用 HTTP_X_FORWARDED_FOR 标头在负载均衡器或其他分布式环境后面获取正确的 IP 很容易。问题是我们如何在 CodeIgniter 中正确实现这个解决方案?正如前面的答案所指出的:编写自己的 IP 函数。问题在于,如果在整个应用程序中调用 ip_address() 会怎样?重写该函数不是更好吗(使用查看正确标题的函数)? CodeIgniter 有一个方便的机制,很方便:

解决方案是扩展 CodeIgniter Input 类,通过在 /application/core 中创建一个名为 MY_Input.php 的新类文件(MY_ 是扩展的可配置前缀,您可以在配置文件中更改它)。使用扩展,您可以创建与原始类方法同名的函数,而不会破坏任何内容,也无需编辑核心文件。 CodeIgniter 将只使用您的新方法。您的扩展输入类将如下所示:

class MY_Input extends CI_Input {

    function __construct()
    {
        parent::__construct();
    }
    //Overide ip_address() with your own function
    function ip_address() 
    {
        //Obtain the IP address however you'd like, you may want to do additional validation, etc..
        $correct_ip_address = $_SERVER['HTTP_X_FORWARDED_FOR'];  
        return $correct_ip_address;
    }
}

通过这种方式,我们在不破坏框架的情况下更改了核心行为,并且整个应用中对 ip_address() 的现有调用现在将使用您的方法。

关于处理链中的其他 IP,如果您只对客户端 IP 感兴趣,那应该没关系。至少使用 AWS 负载均衡器,HTTP_X_FORWARDED_FOR 标头似乎总是包含正确的客户端 IP。

【讨论】:

  • 感谢您的回答!当此标头未设置时,一个简单的修改是编写 ip_address 函数,如下所示:function ip_address() { return getenv('HTTP_X_FORWARDED_FOR') ?: getenv('REMOTE_ADDR'); }
【解决方案2】:

Oliver 的解决方案有效,但在某些情况下,如果您知道正在使用的代理 IP 地址,最好使用以下方法。编辑您的 application/config/config.php 文件以包含以下内容:

$config['proxy_ips'] = '1.2.3.4, 2.3.4.5';

还要注意,标头信息通常不可靠,不应用于安全敏感目的。例如,限制管理员用户仅使用某些白名单 IP 地址的情况并不少见。

【讨论】:

  • 如果代理 IP 已知,这应该是首选解决方案 - 您甚至可以指定子网(例如 192.168.5.0/24 )。
【解决方案3】:
<?php 
function getIPfromXForwarded() 
{ 
    $ipString = @getenv("HTTP_X_FORWARDED_FOR"); 
    $addr     = explode(",",$ipString); 

    return $addr[sizeof($addr)-1]; 
} 
?> 

尝试类似的方法。看看它是否有效。用法:

<? echo getIPfromXForwarded(); ?>

【讨论】:

    【解决方案4】:

    在您的情况下,您可以将指定的负载平衡器 IP 添加到 $config['proxy_ips'] (application/config/config.php),例如:

    $config['proxy_ips'] = ['192.168.1.2'];
    

    动态代理IP:

    根据你的动态IP问题,你可以屏蔽Load-Balancer网络的IP范围,例如:

     $config['proxy_ips'] = '192.168.1.0/24';
    

    在 Codeigniter 3 中可以使用掩码功能


    获取IP方法:

    $this->input->ip_address();
    

    $this 指的是 CI 实例。

    此方法会考虑 $config['proxy_ips'] 设置,并将返回报告的 HTTP_X_FORWARDED_FOR、HTTP_CLIENT_IP、HTTP_X_CLIENT_IP 或 HTTP_X_CLUSTER_CLIENT_IP 地址以获得允许的 IP 地址。

    【讨论】:

    • 这可能是最好的答案,因为它专注于“CodeIgniter 方式”来做到这一点。内置的 $this-&gt;input-&gt;ip_address() 函数做了很多工作来处理不同负载平衡器、反向代理和其他转发代理可能引入的多种情况(如 IP 链接) - 为什么要重新发明那个轮子覆盖它并编写自己的?
    • 很高兴听到这个消息! CI代理IP被视为Web服务器,如Nginx real-ip,它有更多的安全选项。
    【解决方案5】:

    我遇到了 Thava 解决方案的一个版本,该版本非常适用于负载均衡器 IP 可以更改的情况(例如 AWS)并且仍然在本机利用 CI 配置文件。当您知道您在 LB 后面运行时,您可以将 config.php 修改为:

    $config['proxy_ips'] = isset($_SERVER["REMOTE_ADDR"]) ? $_SERVER["REMOTE_ADDR"] : '';
    

    知道 REMOTE_ADDR 将始终是当前的 LB。

    在此感谢 Eric Brown https://expressionengine.com/forums/archive/topic/185751/amazon-load-balancing-and-codeigniter-configproxy_ips#925678

    【讨论】:

      【解决方案6】:

      我知道有一个与您的问题相关并且被您接受的好答案,但是对于未来的用户,我正在分享一个在所有情况下都对我完美运行的功能。

       public function ip()
          {
              $ipaddress = '';
              if ($_SERVER['HTTP_CLIENT_IP'])
                  $ipaddress = $_SERVER['HTTP_CLIENT_IP'];
              else if($_SERVER['HTTP_X_FORWARDED_FOR'])
                  $ipaddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
              else if($_SERVER['HTTP_X_FORWARDED'])
                  $ipaddress = $_SERVER['HTTP_X_FORWARDED'];
              else if($_SERVER['HTTP_FORWARDED_FOR'])
                  $ipaddress = $_SERVER['HTTP_FORWARDED_FOR'];
              else if($_SERVER['HTTP_FORWARDED'])
                  $ipaddress = $_SERVER['HTTP_FORWARDED'];
              else if($_SERVER['REMOTE_ADDR'])
                  $ipaddress = $_SERVER['REMOTE_ADDR'];
              else
                  $ipaddress = 'UNKNOWN';
              echo $ipaddress ;
           }
      

      【讨论】:

        【解决方案7】:

        我在工作中遇到了同样的情况,除了 IP 不是真正的“动态”,而是管理代理和负载平衡器的“基础设施人员”出于未公开的原因经常更改它们。所以我们不得不协商,我们想出了一个解决方案,在他们的配置/配置管理工具中设置一个钩子,以便在某个地方(在运行我们的 Apache/PHP 的用户可以访问的文件夹中)写入一个配置文件。

        所以我使用 CI 挂钩在系统引导程序中读取该文件,以更改我的应用配置,更新代理 IP 列表、缓存路径、cookie 域等值。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-12-24
          • 1970-01-01
          • 1970-01-01
          • 2011-06-08
          • 2011-07-04
          • 2013-07-02
          • 1970-01-01
          • 2021-06-15
          相关资源
          最近更新 更多