如何在PHP webservice中获取客户端的IP地址?

31

我开发了一个PHP Web服务。我想记录消费此Web服务的WS客户端的所有传入连接。如何获取客户端的IP地址?如下所示:

$_SERVER['HTTP_CLIENT_IP']
似乎始终为空。


你解决了吗?$_SERVER的print_r输出是什么? - Ben G
10个回答

50

我试过了,值似乎也为空。我正在本地网络上从Java客户端消费Web服务。也许我只是尝试将所有服务器变量输出以查看它们中是否包含请求的IP地址。 - simon
你使用的是哪个Web服务器和PHP版本,它们的配置如何? - Tom Haigh
1
Web服务器是Apache 2.2.1.1,PHP版本为5.2.8。我正在开发的PHP代码作为KnowledgeTree 3.6.1服务器的一部分运行。我还尝试从(knowledgeTree)内置函数session->resolveIp等中读取IP地址,但没有成功。 - simon

24

实际上,我建议使用这个函数来覆盖所有的情况,比如使用代理、共享网络等:

function getUserIpAddr()
{
    if (!empty($_SERVER['HTTP_CLIENT_IP'])) //if from shared
    {
        return $_SERVER['HTTP_CLIENT_IP'];
    }
    else if (!empty($_SERVER['HTTP_X_FORWARDED_FOR']))   //if from a proxy
    {
        return $_SERVER['HTTP_X_FORWARDED_FOR'];
    }
    else
    {
        return $_SERVER['REMOTE_ADDR'];
    }
}

7
发送伪造的 X-Forwarded-For 标头可以轻松欺骗此功能! - Emil Vikström
好的观点。如果您想捕捉伪造的内容,最好确保 REMOTE_ADDR 和 HTTP_X_FORWARDED_FOR 之间没有不匹配。 - Ben G
实际上,代理的整个意义在于REMOTE_ADDR和HTTP_X_FORWARDED_FOR之间会存在不匹配。 - jayarjo

8
确保不相信客户端发送的数据。$_SERVER['REMOTE_ADDR'] 包含连接方的真实 IP 地址。这是您可以找到的最可靠的值。
但是,他们可能在代理服务器后面,在这种情况下,代理可能已经设置了 $_SERVER['HTTP_X_FORWARDED_FOR'],但这个值很容易被欺骗。它可以被没有代理的某个人设置为用户想要的任何值,或者 IP 可以是代理后面的 LAN 中的内部 IP。
这意味着,如果你要保存 $_SERVER['HTTP_X_FORWARDED_FOR'],请确保你也保存 $_SERVER['REMOTE_ADDR'] 值,例如,通过将两个值保存在数据库的不同字段中。
如果您要将 IP 保存为字符串到数据库中,请确保至少有45个字符的空间。IPv6 已经成为常态,这些地址大于旧的 IPv4 地址。

5

函数getUserIpAddr()和getRealIpAddr()是不可靠的

唯一可靠的IP来自$ ip = $ _SERVER ["REMOTE_ADDR"]; 否则,任何人都可以发送CLIENT_IP标头来伪造他的IP地址。

这个Firefox插件可以帮助您发送自定义标头。将CLIENT_IP = x.x.x.x标头发送到运行此页面上任何函数的服务器,意味着客户端可以选择任何IP ...


2
如果这个不能完成任务,我不知道还有什么能做到了。
    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');
}

1
这可以很容易地通过伪造X-Forwarded-For头来欺骗! - Emil Vikström

2

您是否在使用某种框架来构建您的Web服务?我看到一些框架(例如Agavi)会有意删除所有$SERVER数据,因为它们希望强制您使用来自框架服务的验证过的值。


1
我的首选函数:
    public static function get_remote_ip() {
        if(isset($_SERVER['REMOTE_ADDR']) && !empty($_SERVER['REMOTE_ADDR'])) {
            return $_SERVER['REMOTE_ADDR'];
        } 

        if(isset($_SERVER['HTTP_X_FORWARDED_FOR']) && !empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            return $_SERVER['HTTP_X_FORWARDED_FOR'];
        }

        return null;
    }

0

你可以尝试

<?php
var_dump($_SERVER);

查看所有变量。但这也取决于你的脚本运行的后端是什么。是 Apache 吗?


0
<?php 
 $ip=$_SERVER['REMOTE_ADDR'];
 echo "Your IP Address is $ip"; 
 ?> 

而要插入数据库,只需使用$ip即可。


-1
<?php
function getIP() {
$ip;
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("REMOTE_ADDR"))
$ip = getenv("REMOTE_ADDR");
else
$ip = "UNKNOWN";
return $ip;

}

//-----------------------------------------------

//Usage:


$client_ip=getIP();
echo "Your IP :".$client_ip;
?>

这很容易被伪造的假X-Forwarded-For头部所欺骗。 - Emil Vikström
然后您可以尝试使用$_SERVER来获取客户端的信息。这只是另一种可以使用的方法。 - Tarun Gupta
我的反对意见是将 X-Forwarded-For 和 Client-IP HTTP 标头视为与远程地址相同(甚至更好!)。它们并不相同。它们很容易被伪造,因此除非在内部网络中,否则不应完全信任它们。如果您要读取这些标头,请确保同时保存真正的远程地址。您的函数根本没有反映出这一点,因此我希望没有人在实际环境中使用这个函数。 - Emil Vikström
Emil Vikstrom..这就是我回复的另一种方式,我并不建议任何人这样做。 - Tarun Gupta

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接