php获取客户端IP

比较 HTTP_CLIENT_IP HTTP_X_FORWARDED_FOR REMOTE_ADDR

最近做项目的时候,遇到一个需要记录客户端ip的,后台语言是php,我想了一下,用REMOTE_ADDR吧。可是呢,后来发现其实这个还有很多其他的获取方式,HTTP_CLIENT_IP, HTTP_X_FORWARDED_FOR都可以获取,我仔细查了一下资料,总结一下这三者的区别,另附完整解决方法:

  1. HTTP_CLIENT_IP头是有的,只是未成标准,不一定服务器都实现了。
  2. HTTP_X_FORWARDED_FOR 是有标准定义,用来识别经过HTTP代理后的客户端IP地址,格式:clientip,proxy1,proxy2。详细解释见 http://zh.wikipedia.org/wiki/X-Forwarded-For
  3. REMOTE_ADDR 是可靠的, 它是最后一个跟你的服务器握手的IP,可能是用户的代理服务器,也可能是自己的反向代理。

顺便说下$_SERVER和getenv的区别,getenv不支持IIS的isapi方式运行的php

function getIp() {
    if (getenv ( "HTTP_CLIENT_IP" ) && strcasecmp ( getenv ( "HTTP_CLIENT_IP" ), "unknown" )) {
        $ip = getenv ( "HTTP_CLIENT_IP" );
    } elseif (getenv ( "HTTP_X_FORWARDED_FOR" ) && strcasecmp ( getenv ( "HTTP_X_FORWARDED_FOR" ), "unknown" )) {
        $ip = getenv ( "HTTP_X_FORWARDED_FOR" );
    } elseif (getenv ( "REMOTE_ADDR" ) && strcasecmp ( getenv ( "REMOTE_ADDR" ), "unknown" )) {
        $ip = getenv ( "REMOTE_ADDR" );
    } elseif (isset ( $_SERVER ['REMOTE_ADDR'] ) && $_SERVER ['REMOTE_ADDR'] && strcasecmp ( $_SERVER ['REMOTE_ADDR'], "unknown" )) {
        $ip = $_SERVER ['REMOTE_ADDR'];
    } else {
        $ip = "unknown";
    }
    return ($ip);
}

REMOTE_ADDR不可以显式的伪造,虽然可以通过代理将ip地址隐藏,但是这个地址仍然具有参考价值,因为它就是与你的服务器实际连接的ip地址。

相比之下,前两种ip地址都可以通过http header来伪造,但并不意味着它们一无是处。生产环境中很多服务器隐藏在负载均衡节点后面,你通过REMOTE_ADDR只能获取到负载均衡节点的ip地址,一般的负载均衡节点会把前端实际的ip地址通过HTTP_CLIENT_IP或者HTTP_X_FORWARDED_FOR这两种http头传递过来

你可能感兴趣的:(php获取客户端IP)