php 使用 codeigniter 检索用户的真实 IP
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14491043/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Retrieve real IP of user using codeigniter
提问by Zaki Aziz
My app tracks the IP address of users logging into the site. The tracking was working fine on a regular web server (we were on hostgator) but seemed to start tracking odd IP addresses when we switch to a PaaS platform (pagodabox) After speaking to pagodabox support they informed me that the IPs codeigniter was picking up was the IPs of the load balancers/routers of pagodabox and to get a user's actual IP address I would have to utilize HTTP_X_FORWARDED_FOR
我的应用程序会跟踪登录该站点的用户的 IP 地址。跟踪在常规 Web 服务器上运行良好(我们在 hostgator 上)但是当我们切换到 PaaS 平台(宝塔盒)时似乎开始跟踪奇怪的 IP 地址在与宝塔盒支持人员交谈后,他们告诉我 IP 代码点火器正在接收是pagodabox 的负载均衡器/路由器的 IP 并获取用户的实际 IP 地址,我必须使用HTTP_X_FORWARDED_FOR
I was using codeigniter's input class function $this->input->ip_address()to retreive the user's IP. I looked at the function and noticed they had some sort of features to retreive the HTTP_X_FORWARDED_FORIP value but I am not sure how to use it. Do i have to change/add something in the config?
我正在使用 codeigniter 的输入类函数$this->input->ip_address()来检索用户的 IP。我查看了该函数并注意到它们具有某种功能来检索 HTTP_X_FORWARDED_FORIP 值,但我不确定如何使用它。我是否必须在配置中更改/添加某些内容?
EDIT: After a few users have pointed out where I should add in the list of IP addresses of load balancers a new question came up: What would I do if the list of IP's change frequently? (ie no static IP, all dynamic)
编辑:在一些用户指出我应该在负载均衡器的 IP 地址列表中添加的位置之后,出现了一个新问题:如果 IP 列表频繁更改,我该怎么办?(即无静态IP,全动态)
回答by Oliver Holmberg
I'm sure you've resolved this by now, but I thought I would post the correct answer for future reference. I came across this same problem (Using load balancers on AWS with a CodeIgniter app.) As you pointed out, it's easy enough to get the correct IP behind a load balancer or other distributed environment using the HTTP_X_FORWARDED_FOR header. The problem is how do we correctly implement this solution in CodeIgniter? As the previous answer points out: Write your own IP function. The problem with this, is what if ip_address() is called throughout your app? Wouldn't it be better to override that function (With one that looks at the correct header)? CodeIgniter has a convenient mechanism for this, which is handy:
我相信你现在已经解决了这个问题,但我想我会发布正确的答案以供将来参考。我遇到了同样的问题(在 AWS 上使用带有 CodeIgniter 应用程序的负载均衡器。)正如您所指出的,使用 HTTP_X_FORWARDED_FOR 标头在负载均衡器或其他分布式环境后面获取正确的 IP 很容易。问题是我们如何在 CodeIgniter 中正确实现这个解决方案?正如前面的回答所指出的:编写自己的 IP 函数。问题是,如果在整个应用程序中都调用 ip_address() 会怎样?覆盖该功能(使用查看正确标题的功能)不是更好吗?CodeIgniter 有一个方便的机制,它很方便:
The solution is to extend the CodeIgniter Input class, by creating a new class file in /application/core called MY_Input.php (MY_ is a configurable prefix for extensions, you can change it in your config file). With extensions, you can create a function of the SAME name as the original class method without breaking anything, and without editing core files. CodeIgniter will just use your new method instead. Your extended input class will look something like this:
解决方案是扩展 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;
}
}
This way we've changed the core behavior without hacking the framework, and existing calls to ip_address() throughout your app will now be using your method.
通过这种方式,我们在不破坏框架的情况下更改了核心行为,整个应用程序中对 ip_address() 的现有调用现在将使用您的方法。
With regards to dealing with other IP's in the chain, if you're only interested in the client IP, it shouldn't matter. With AWS load balancers at least, the HTTP_X_FORWARDED_FOR header seems to always contain the correct client IP.
关于处理链中的其他 IP,如果您只对客户端 IP 感兴趣,则无关紧要。至少使用 AWS 负载均衡器,HTTP_X_FORWARDED_FOR 标头似乎总是包含正确的客户端 IP。
回答by Thava
Oliver's solution works, but in some circumstances, it is better to use the following if you know the proxy IP addresses that are in use. Edit your application/config/config.php file to include the following:
Oliver 的解决方案有效,但在某些情况下,如果您知道正在使用的代理 IP 地址,最好使用以下解决方案。编辑您的 application/config/config.php 文件以包含以下内容:
$config['proxy_ips'] = '1.2.3.4, 2.3.4.5';
Also be aware of the fact that the header information is usually unreliable and should not be used for security sensitive purposes. For example, it is not uncommon to restrict admin users to use only some white listed IP addresses.
另请注意,标头信息通常不可靠,不应用于安全敏感目的。例如,限制管理员用户只能使用一些白名单 IP 地址的情况并不少见。
回答by edwardmp
<?php
function getIPfromXForwarded()
{
$ipString = @getenv("HTTP_X_FORWARDED_FOR");
$addr = explode(",",$ipString);
return $addr[sizeof($addr)-1];
}
?>
Try something like that. See if it works. Usage:
尝试这样的事情。看看它是否有效。用法:
<? echo getIPfromXForwarded(); ?>
回答by Imran Qamer
I know there is a good answer which is relevant to your question and is accepted by you but for future users I am sharing a function which is working perfectly for me in all situations.
我知道有一个很好的答案与您的问题相关并被您接受,但对于未来的用户,我正在分享一个在所有情况下都对我来说完美的功能。
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 ;
}
回答by JSJ
I came across a version of Thava's solution that works great for situations where the load balancer IPs can change (such as AWS) and still leverages CIs configuration files natively. When you know you are running behind an LB you can modify config.php to be:
我遇到了 Thava 解决方案的一个版本,它非常适用于负载均衡器 IP 可以更改(例如 AWS)并且仍然在本机利用 CI 配置文件的情况。当您知道自己在 LB 后面运行时,您可以将 config.php 修改为:
$config['proxy_ips'] = isset($_SERVER["REMOTE_ADDR"]) ? $_SERVER["REMOTE_ADDR"] : '';
Knowing that REMOTE_ADDR will always be the current LB.
知道 REMOTE_ADDR 将始终是当前的 LB。
Thanks to Eric Brown here https://expressionengine.com/forums/archive/topic/185751/amazon-load-balancing-and-codeigniter-configproxy_ips#925678
在此感谢 Eric Brown https://expressionengine.com/forums/archive/topic/185751/amazon-load-balancing-and-codeigniter-configproxy_ips#925678
回答by Nick Tsai
In your case, you can add specified Load-Balancer IP into $config['proxy_ips'](application/config/config.php), for example:
在您的情况下,您可以将指定的负载均衡器 IP 添加到$config['proxy_ips']( application/config/config.php) 中,例如:
$config['proxy_ips'] = ['192.168.1.2'];
Dynamic proxy IP:
动态代理IP:
According to your dynamic IP problem, you can mask the IP range for the Load-Balancer network, for example:
根据您的动态 IP 问题,您可以屏蔽负载均衡器网络的 IP 范围,例如:
$config['proxy_ips'] = '192.168.1.0/24';
The mask function is able in Codeigniter 3
在 Codeigniter 3 中可以使用掩码功能
Get IP method:
获取IP方法:
$this->input->ip_address();
While $thisrefers to CI instance.
while$this指的是 CI 实例。
This method takes into account the $config['proxy_ips'] setting and will return the reported HTTP_X_FORWARDED_FOR, HTTP_CLIENT_IP, HTTP_X_CLIENT_IP or HTTP_X_CLUSTER_CLIENT_IP address for the allowed IP addresses.
此方法考虑了 $config['proxy_ips'] 设置,并将返回报告的 HTTP_X_FORWARDED_FOR、HTTP_CLIENT_IP、HTTP_X_CLIENT_IP 或 HTTP_X_CLUSTER_CLIENT_IP 地址作为允许的 IP 地址。
回答by Stefano Mozart
I had the same kind of situation at work, except that the IPs were not really 'dynamic', but the the 'infrastructure people' managing proxyies and load balancers used to change them for undisclosed reasons. So we had to negotiate and we came up with a solution setting up a hook in their configuration/provision management tool to write a config file somewhere (in a folder accessible to the user running our Apache/PHP).
我在工作中遇到了同样的情况,除了 IP 并不是真正的“动态”,但是管理代理和负载均衡器的“基础设施人员”过去常常出于未公开的原因更改它们。所以我们不得不协商,我们想出了一个解决方案,在他们的配置/供应管理工具中设置一个钩子,在某个地方(在运行我们的 Apache/PHP 的用户可以访问的文件夹中)编写一个配置文件。
So I used a CI hook to read that file on system bootstrap in order to change my apps config, updating values like the proxy IP list, cache path, cookie domain etc.
因此,我使用 CI 钩子在系统引导程序上读取该文件,以更改我的应用程序配置,更新代理 IP 列表、缓存路径、cookie 域等值。

