From 2d80494b612dd19febfd7a9aeecc695eb301669e Mon Sep 17 00:00:00 2001 From: zhang chu Date: Tue, 31 May 2016 18:59:41 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=20get=5Fclient=5Fip=20?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E7=9A=84adv=E6=A8=A1=E5=BC=8F=E7=9A=84?= =?UTF-8?q?=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 之前的代码在对 HTTP_X_FORWARDED_FOR 内容进行 array_search 和 unset 操作是没有意义的。 2. 最重要的是,在一些网络架构下,HTTP_X_FORWARDED_FOR 开始部分中会包含一些内网地址,这些地址对于get_client_ip的逻辑是无用的。 3. 为此增加了两个函数,is_inner_ip和get_first_outerip --- ThinkPHP/Common/functions.php | 57 +++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 13 deletions(-) diff --git a/ThinkPHP/Common/functions.php b/ThinkPHP/Common/functions.php index b06dff8e7..2c7cc1a62 100644 --- a/ThinkPHP/Common/functions.php +++ b/ThinkPHP/Common/functions.php @@ -1644,6 +1644,45 @@ function load_ext_file($path) } } +/** + * 判断一个ip是否是内网ip + * A类 10.0.0.0--10.255.255.255 + * B类 172.16.0.0--172.31.255.255 + * C类 192.168.0.0--192.168.255.255 + * @param string $ip + * @return boolean + */ +function is_inner_ip($ip) +{ + if ('127.0.0.1' === $ip) { + return true; + } + list($i1, $i2, $i3, $i4) = explode('.', $ip, 4); + return ($i1 == 10 || ($i1 == 172 && 16 <= $i2 && $i2 < 32) || ($i1 == 192 && $i2 == 168)); +} + +/** + * 获取一堆ip里面的第一个外网ip,如果没有外网ip,返回最后一个合法的ip,否则返回 unknown + * @param string $iplist + * @return string + */ +function get_first_outerip($iplist) +{ + $iparr = preg_split('/;|,|\s/', $iplist); + $ip = 'unknown'; + foreach ($iparr as $v) { + $v = trim($v); + if (false === ip2long($v)) { + continue; + } + $ip = $v; + if (!is_inner_ip($ip)) { + break; + } + } + return $ip; +} + /** * 获取客户端IP地址 * @param integer $type 返回类型 0 返回IP地址 1 返回IPV4地址数字 @@ -1659,19 +1698,11 @@ function get_client_ip($type = 0, $adv = false) } if ($adv) { - if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { - $arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']); - $pos = array_search('unknown', $arr); - if (false !== $pos) { - unset($arr[$pos]); - } - - $ip = trim($arr[0]); - } elseif (isset($_SERVER['HTTP_CLIENT_IP'])) { - $ip = $_SERVER['HTTP_CLIENT_IP']; - } elseif (isset($_SERVER['REMOTE_ADDR'])) { - $ip = $_SERVER['REMOTE_ADDR']; - } + $ip = $_SERVER['HTTP_X_FORWARDED_FOR'] + .' '.$_SERVER['HTTP_CLIENT_IP'] + .' '.$_SERVER['HTTP_VIA'] + .' '.$_SERVER['REMOTE_ADDR']; + $ip = get_first_outerip($ip); } elseif (isset($_SERVER['REMOTE_ADDR'])) { $ip = $_SERVER['REMOTE_ADDR']; }