简体   繁体   English

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

[英]How to get the client IP address in PHP

How can I get the client IP address using PHP?如何使用 PHP 获取客户端 IP 地址?

I want to keep record of the user who logged into my website through his/her IP address.我想记录通过他/她的 IP 地址登录我网站的用户。

Whatever you do, make sure not to trust data sent from the client.无论您做什么,请确保不要信任从客户端发送的数据。 $_SERVER['REMOTE_ADDR'] contains the real IP address of the connecting party. $_SERVER['REMOTE_ADDR']包含连接方的真实 IP 地址。 That is the most reliable value you can find.这是您能找到的最可靠的值。

However, they can be behind a proxy server in which case the proxy may have set the $_SERVER['HTTP_X_FORWARDED_FOR'] , but this value is easily spoofed.但是,它们可能位于代理服务器后面,在这种情况下,代理可能已经设置了$_SERVER['HTTP_X_FORWARDED_FOR'] ,但这个值很容易被欺骗。 For example, it can be set by someone without a proxy, or the IP can be an internal IP from the LAN behind the proxy.例如,它可以由没有代理的人设置,或者 IP 可以是来自代理后面的 LAN 的内部 IP。

This means that if you are going to save the $_SERVER['HTTP_X_FORWARDED_FOR'] , make sure you also save the $_SERVER['REMOTE_ADDR'] value.这意味着如果您要保存$_SERVER['HTTP_X_FORWARDED_FOR'] ,请确保您保存了$_SERVER['REMOTE_ADDR']值。 Eg by saving both values in different fields in your database.例如,通过将这两个值保存在数据库的不同字段中。

If you are going to save the IP to a database as a string, make sure you have space for at least 45 characters .如果要将 IP 作为字符串保存到数据库,请确保至少有45 个字符的空间。 IPv6 is here to stay and those addresses are larger than the older IPv4 addresses. IPv6将继续存在,并且这些地址比旧的 IPv4 地址更大。

(Note that IPv6 usually uses 39 characters at most but there is also a special IPv6 notation for IPv4 addresses which in its full form can be up to 45 characters. So if you know what you are doing you can use 39 characters, but if you just want to set and forget it, use 45). (请注意,IPv6 通常最多使用 39 个字符,但对于 IPv4 地址也有一个特殊的 IPv6 表示法,其完整形式最多可包含 45 个字符。因此,如果您知道自己在做什么,则可以使用 39 个字符,但如果您只是想设置并忘记它,使用45)。

$_SERVER['REMOTE_ADDR'] may not actually contain real client IP addresses, as it will give you a proxy address for clients connected through a proxy, for example. $_SERVER['REMOTE_ADDR']实际上可能不包含真实的客户端 IP 地址,因为它会给你一个代理地址,用于通过代理连接的客户端,例如。 That may well be what you really want, though, depending what your doing with the IPs.不过,这很可能是您真正想要的,这取决于您对 IP 的处理方式。 Someone's private RFC1918 address may not do you any good if you're say, trying to see where your traffic is originating from, or remembering what IP the user last connected from, where the public IP of the proxy or NAT gateway might be the more appropriate to store.如果您说某人的私有 RFC1918 地址可能对您没有任何好处,试图查看您的流量来自哪里,或者记住用户上次连接的 IP,代理或 NAT 网关的公共 IP 可能更多适合存放。

There are several HTTP headers like X-Forwarded-For which may or may not be set by various proxies.有几个 HTTP 标头,例如X-Forwarded-For ,可能会或可能不会由各种代理设置。 The problem is that those are merely HTTP headers which can be set by anyone.问题是这些只是任何人都可以设置的 HTTP 标头。 There's no guarantee about their content.他们的内容无法保证。 $_SERVER['REMOTE_ADDR'] is the actual physical IP address that the web server received the connection from and that the response will be sent to. $_SERVER['REMOTE_ADDR']是 Web 服务器从其接收连接并将响应发送到的实际物理 IP 地址。 Anything else is just arbitrary and voluntary information.其他任何信息都只是任意和自愿的信息。 There's only one scenario in which you can trust this information: you are controlling the proxy that sets this header.只有一种情况可以信任此信息:您正在控制设置此标头的代理。 Meaning only if you know 100% where and how the header was set should you heed it for anything of importance.这意味着只有当您 100% 知道标头的设置位置和方式时,您才应该注意任何重要的事情。

Having said that, here's some sample code:话虽如此,这里有一些示例代码:

if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
    $ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
    $ip = $_SERVER['REMOTE_ADDR'];
}

Editor's note: Using the above code has security implications .编者注:使用上述代码有安全隐患 The client can set all HTTP header information (ie. $_SERVER['HTTP_... ) to any arbitrary value it wants.客户端可以将所有 HTTP 标头信息(即$_SERVER['HTTP_... )设置为它想要的任意值。 As such it's far more reliable to use $_SERVER['REMOTE_ADDR'] , as this cannot be set by the user.因此,使用$_SERVER['REMOTE_ADDR']更可靠,因为用户无法设置。

From:从: http://roshanbh.com.np/2007/12/getting-real-ip-address-in-php.html http://roshanbh.com.np/2007/12/getting-real-ip-address-in-php.html

Here is a cleaner code sample of a good way to get the IP address of the user.这是获取用户 IP 地址的好方法的更简洁的代码示例。

$ip = $_SERVER['HTTP_CLIENT_IP'] 
   ? $_SERVER['HTTP_CLIENT_IP'] 
   : ($_SERVER['HTTP_X_FORWARDED_FOR'] 
        ? $_SERVER['HTTP_X_FORWARDED_FOR'] 
        : $_SERVER['REMOTE_ADDR']);

Here is a shorter version that uses the elvis operator:这是使用 elvis 运算符的较短版本:

$_SERVER['HTTP_CLIENT_IP'] 
   ? : ($_SERVER['HTTP_X_FORWARDED_FOR'] 
   ? : $_SERVER['REMOTE_ADDR']);

Here is a version that uses isset to remove notices (thank you, @shasi kanth):这是一个使用 isset 删除通知的版本(谢谢你,@shasi kanth):

$ip = isset($_SERVER['HTTP_CLIENT_IP']) 
    ? $_SERVER['HTTP_CLIENT_IP'] 
    : (isset($_SERVER['HTTP_X_FORWARDED_FOR']) 
      ? $_SERVER['HTTP_X_FORWARDED_FOR'] 
      : $_SERVER['REMOTE_ADDR']);

它应该包含在$_SERVER['REMOTE_ADDR']变量中。

My favourite solution is the way Zend Framework 2 uses.我最喜欢的解决方案是 Zend Framework 2 的使用方式。 It also considers the $_SERVER properties HTTP_X_FORWARDED_FOR , HTTP_CLIENT_IP , REMOTE_ADDR but it declares a class for it to set some trusted proxies and it returns one IP address not an array.它还考虑了$_SERVER属性HTTP_X_FORWARDED_FORHTTP_CLIENT_IPREMOTE_ADDR ,但它声明了一个类来设置一些受信任的代理,它返回一个 IP 地址而不是数组。 I think this is the solution that comes closest to it:我认为这是最接近它的解决方案:

class RemoteAddress
{
    /**
     * Whether to use proxy addresses or not.
     *
     * As default this setting is disabled - IP address is mostly needed to increase
     * security. HTTP_* are not reliable since can easily be spoofed. It can be enabled
     * just for more flexibility, but if user uses proxy to connect to trusted services
     * it's his/her own risk, only reliable field for IP address is $_SERVER['REMOTE_ADDR'].
     *
     * @var bool
     */
    protected $useProxy = false;

    /**
     * List of trusted proxy IP addresses
     *
     * @var array
     */
    protected $trustedProxies = array();

    /**
     * HTTP header to introspect for proxies
     *
     * @var string
     */
    protected $proxyHeader = 'HTTP_X_FORWARDED_FOR';

    // [...]

    /**
     * Returns client IP address.
     *
     * @return string IP address.
     */
    public function getIpAddress()
    {
        $ip = $this->getIpAddressFromProxy();
        if ($ip) {
            return $ip;
        }

        // direct IP address
        if (isset($_SERVER['REMOTE_ADDR'])) {
            return $_SERVER['REMOTE_ADDR'];
        }

        return '';
    }

    /**
     * Attempt to get the IP address for a proxied client
     *
     * @see http://tools.ietf.org/html/draft-ietf-appsawg-http-forwarded-10#section-5.2
     * @return false|string
     */
    protected function getIpAddressFromProxy()
    {
        if (!$this->useProxy
            || (isset($_SERVER['REMOTE_ADDR']) && !in_array($_SERVER['REMOTE_ADDR'], $this->trustedProxies))
        ) {
            return false;
        }

        $header = $this->proxyHeader;
        if (!isset($_SERVER[$header]) || empty($_SERVER[$header])) {
            return false;
        }

        // Extract IPs
        $ips = explode(',', $_SERVER[$header]);
        // trim, so we can compare against trusted proxies properly
        $ips = array_map('trim', $ips);
        // remove trusted proxy IPs
        $ips = array_diff($ips, $this->trustedProxies);

        // Any left?
        if (empty($ips)) {
            return false;
        }

        // Since we've removed any known, trusted proxy servers, the right-most
        // address represents the first IP we do not know about -- i.e., we do
        // not know if it is a proxy server, or a client. As such, we treat it
        // as the originating IP.
        // @see http://en.wikipedia.org/wiki/X-Forwarded-For
        $ip = array_pop($ips);
        return $ip;
    }

    // [...]
}

See the full code here: https://raw.githubusercontent.com/zendframework/zend-http/master/src/PhpEnvironment/RemoteAddress.php在此处查看完整代码: https ://raw.githubusercontent.com/zendframework/zend-http/master/src/PhpEnvironment/RemoteAddress.php

There are different types of users behind the Internet, so we want to catch the IP address from different portions.互联网背后有不同类型的用户,所以我们想从不同的部分捕获IP地址。 Those are:那些是:

1. $_SERVER['REMOTE_ADDR'] - This contains the real IP address of the client. 1. $_SERVER['REMOTE_ADDR'] - 这包含客户端的真实 IP 地址。 That is the most reliable value you can find from the user.这是您可以从用户那里找到的最可靠的价值。

2. $_SERVER['REMOTE_HOST'] - This will fetch the host name from which the user is viewing the current page. 2. $_SERVER['REMOTE_HOST'] - 这将获取用户正在查看当前页面的主机名。 But for this script to work, hostname lookups on inside httpd.conf must be configured.但是为了使这个脚本工作,必须配置在 httpd.conf 中的主机名查找。

3. $_SERVER['HTTP_CLIENT_IP'] - This will fetch the IP address when the user is from shared Internet services. 3. $_SERVER['HTTP_CLIENT_IP'] - 当用户来自共享 Internet 服务时,这将获取 IP 地址。

4. $_SERVER['HTTP_X_FORWARDED_FOR'] - This will fetch the IP address from the user when he/she is behind the proxy. 4. $_SERVER['HTTP_X_FORWARDED_FOR'] - 当他/她在代理后面时,这将从用户那里获取 IP 地址。

So we can use this following combined function to get the real IP address from users who are viewing in diffrent positions,因此,我们可以使用以下组合功能从不同位置查看的用户获取真实 IP 地址,

// Function to get the user IP address
function getUserIP() {
    $ipaddress = '';
    if (isset($_SERVER['HTTP_CLIENT_IP']))
        $ipaddress = $_SERVER['HTTP_CLIENT_IP'];
    else if(isset($_SERVER['HTTP_X_FORWARDED_FOR']))
        $ipaddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
    else if(isset($_SERVER['HTTP_X_FORWARDED']))
        $ipaddress = $_SERVER['HTTP_X_FORWARDED'];
    else if(isset($_SERVER['HTTP_X_CLUSTER_CLIENT_IP']))
        $ipaddress = $_SERVER['HTTP_X_CLUSTER_CLIENT_IP'];
    else if(isset($_SERVER['HTTP_FORWARDED_FOR']))
        $ipaddress = $_SERVER['HTTP_FORWARDED_FOR'];
    else if(isset($_SERVER['HTTP_FORWARDED']))
        $ipaddress = $_SERVER['HTTP_FORWARDED'];
    else if(isset($_SERVER['REMOTE_ADDR']))
        $ipaddress = $_SERVER['REMOTE_ADDR'];
    else
        $ipaddress = 'UNKNOWN';
    return $ipaddress;
}

The following is the most advanced method I have found, and I have already tried some others in the past.以下是我找到的最先进的方法,过去我已经尝试过其他一些方法。 It is valid to ensure to get the IP address of a visitor (but please note that any hacker could falsify the IP address easily).确保获取访问者的IP地址是有效的(但请注意,任何黑客都可以轻易伪造IP地址)。

function get_ip_address() {

    // Check for shared Internet/ISP IP
    if (!empty($_SERVER['HTTP_CLIENT_IP']) && validate_ip($_SERVER['HTTP_CLIENT_IP'])) {
        return $_SERVER['HTTP_CLIENT_IP'];
    }

    // Check for IP addresses passing through proxies
    if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {

        // Check if multiple IP addresses exist in var
        if (strpos($_SERVER['HTTP_X_FORWARDED_FOR'], ',') !== false) {
            $iplist = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
            foreach ($iplist as $ip) {
                if (validate_ip($ip))
                    return $ip;
            }
        }
        else {
            if (validate_ip($_SERVER['HTTP_X_FORWARDED_FOR']))
                return $_SERVER['HTTP_X_FORWARDED_FOR'];
        }
    }
    if (!empty($_SERVER['HTTP_X_FORWARDED']) && validate_ip($_SERVER['HTTP_X_FORWARDED']))
        return $_SERVER['HTTP_X_FORWARDED'];
    if (!empty($_SERVER['HTTP_X_CLUSTER_CLIENT_IP']) && validate_ip($_SERVER['HTTP_X_CLUSTER_CLIENT_IP']))
        return $_SERVER['HTTP_X_CLUSTER_CLIENT_IP'];
    if (!empty($_SERVER['HTTP_FORWARDED_FOR']) && validate_ip($_SERVER['HTTP_FORWARDED_FOR']))
        return $_SERVER['HTTP_FORWARDED_FOR'];
    if (!empty($_SERVER['HTTP_FORWARDED']) && validate_ip($_SERVER['HTTP_FORWARDED']))
        return $_SERVER['HTTP_FORWARDED'];

    // Return unreliable IP address since all else failed
    return $_SERVER['REMOTE_ADDR'];
}

/**
 * Ensures an IP address is both a valid IP address and does not fall within
 * a private network range.
 */
function validate_ip($ip) {

    if (strtolower($ip) === 'unknown')
        return false;

    // Generate IPv4 network address
    $ip = ip2long($ip);

    // If the IP address is set and not equivalent to 255.255.255.255
    if ($ip !== false && $ip !== -1) {
        // Make sure to get unsigned long representation of IP address
        // due to discrepancies between 32 and 64 bit OSes and
        // signed numbers (ints default to signed in PHP)
        $ip = sprintf('%u', $ip);

        // Do private network range checking
        if ($ip >= 0 && $ip <= 50331647)
            return false;
        if ($ip >= 167772160 && $ip <= 184549375)
            return false;
        if ($ip >= 2130706432 && $ip <= 2147483647)
            return false;
        if ($ip >= 2851995648 && $ip <= 2852061183)
            return false;
        if ($ip >= 2886729728 && $ip <= 2887778303)
            return false;
        if ($ip >= 3221225984 && $ip <= 3221226239)
            return false;
        if ($ip >= 3232235520 && $ip <= 3232301055)
            return false;
        if ($ip >= 4294967040)
            return false;
    }
    return true;
}

The answer is to use $_SERVER variable.答案是使用$_SERVER变量。 For example, $_SERVER["REMOTE_ADDR"] would return the client's IP address.例如, $_SERVER["REMOTE_ADDR"]将返回客户端的 IP 地址。

A quick solution (error free)快速解决方案(无错误)

function getClientIP():string
{
    $keys=array('HTTP_CLIENT_IP','HTTP_X_FORWARDED_FOR','HTTP_X_FORWARDED','HTTP_FORWARDED_FOR','HTTP_FORWARDED','REMOTE_ADDR');
    foreach($keys as $k)
    {
        if (!empty($_SERVER[$k]) && filter_var($_SERVER[$k], FILTER_VALIDATE_IP))
        {
            return $_SERVER[$k];
        }
    }
    return "UNKNOWN";
}
function get_client_ip()
{
    foreach (array(
                'HTTP_CLIENT_IP',
                'HTTP_X_FORWARDED_FOR',
                'HTTP_X_FORWARDED',
                'HTTP_X_CLUSTER_CLIENT_IP',
                'HTTP_FORWARDED_FOR',
                'HTTP_FORWARDED',
                'REMOTE_ADDR') as $key) {
        if (array_key_exists($key, $_SERVER)) {
            foreach (explode(',', $_SERVER[$key]) as $ip) {
                $ip = trim($ip);
                if ((bool) filter_var($ip, FILTER_VALIDATE_IP,
                                FILTER_FLAG_IPV4 |
                                FILTER_FLAG_NO_PRIV_RANGE |
                                FILTER_FLAG_NO_RES_RANGE)) {
                    return $ip;
                }
            }
        }
    }
    return null;
}

Or the compressed version:或者压缩版:

function get_ip() {
    foreach (array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR') as $key) {
        if (array_key_exists($key, $_SERVER) === true) {
            foreach (array_map('trim', explode(',', $_SERVER[$key])) as $ip) {
                if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false) {
                    return $ip;
                }
            }
        }
    }
}

Here's a bit of code that should pick a valid IP by checking through various sources.这里有一段代码应该通过检查各种来源来选择一个有效的 IP。

First, it checks if 'REMOTE_ADDR' is a public IP or not (and not one of your trusted reverse proxies), then goes through one of the HTTP headers until it finds a public IP and returns it.首先,它检查“REMOTE_ADDR”是否是公共 IP(而不是您信任的反向代理之一),然后遍历其中一个 HTTP 标头,直到找到公共 IP 并返回它。 (PHP 5.2+) (PHP 5.2+)

It should be reliable as long as the reverse proxy is trusted or the server is directly connected with the client.只要反向代理受信任或服务器与客户端直接连接,它就应该是可靠的。

//Get client's IP or null if nothing looks valid
function ip_get($allow_private = false)
{
  //Place your trusted proxy server IPs here.
  $proxy_ip = ['127.0.0.1'];

  //The header to look for (Make sure to pick the one that your trusted reverse proxy is sending or else you can get spoofed)
  $header = 'HTTP_X_FORWARDED_FOR'; //HTTP_CLIENT_IP, HTTP_X_FORWARDED, HTTP_FORWARDED_FOR, HTTP_FORWARDED

  //If 'REMOTE_ADDR' seems to be a valid client IP, use it.
  if(ip_check($_SERVER['REMOTE_ADDR'], $allow_private, $proxy_ip)) return $_SERVER['REMOTE_ADDR'];

  if(isset($_SERVER[$header]))
  {
    //Split comma separated values [1] in the header and traverse the proxy chain backwards.
    //[1] https://en.wikipedia.org/wiki/X-Forwarded-For#Format
    $chain = array_reverse(preg_split('/\s*,\s*/', $_SERVER[$header]));
    foreach($chain as $ip) if(ip_check($ip, $allow_private, $proxy_ip)) return $ip;
  }

   return null;
}

//Check for valid IP. If 'allow_private' flag is set to truthy, it allows private IP ranges as valid client IP as well. (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
//Pass your trusted reverse proxy IPs as $proxy_ip to exclude them from being valid.
function ip_check($ip, $allow_private = false, $proxy_ip = [])
{
  if(!is_string($ip) || is_array($proxy_ip) && in_array($ip, $proxy_ip)) return false;
  $filter_flag = FILTER_FLAG_NO_RES_RANGE;

  if(!$allow_private)
  {
    //Disallow loopback IP range which doesn't get filtered via 'FILTER_FLAG_NO_PRIV_RANGE' [1]
    //[1] https://www.php.net/manual/en/filter.filters.validate.php
    if(preg_match('/^127\.$/', $ip)) return false;
    $filter_flag |= FILTER_FLAG_NO_PRIV_RANGE;
  }

  return filter_var($ip, FILTER_VALIDATE_IP, $filter_flag) !== false;
}

As all others said before you can use $_SERVER['REMOTE_ADDR'];正如所有其他人所说,您可以使用$_SERVER['REMOTE_ADDR']; to get the client IP address.获取客户端 IP 地址。

Also, if you need more information about a user, you can use this:此外,如果您需要有关用户的更多信息,可以使用以下命令:

<?php
    $ip = '0.0.0.0';
    $ip = $_SERVER['REMOTE_ADDR'];
    $clientDetails = json_decode(file_get_contents("http://ipinfo.io/$ip/json"));
    echo "You're logged in from: <b>" . $clientDetails->country . "</b>";
?>

Client's more specific information goes in $clientDetails.客户更具体的信息在 $clientDetails 中。
You can fetch JSON items stored in $clientDetails variable this way: $clientDetails->PostalCode/hostname/region/loc...您可以通过以下方式获取存储在 $clientDetails 变量中的 JSON 项目:$clientDetails->PostalCode/hostname/region/loc...

I'm using ipinfo.io to get extra information.我正在使用ipinfo.io来获取额外信息。

$ip = "";

if (!empty($_SERVER["HTTP_CLIENT_IP"]))
{
    // Check for IP address from shared Internet
    $ip = $_SERVER["HTTP_CLIENT_IP"];
}
elseif (!empty($_SERVER["HTTP_X_FORWARDED_FOR"]))
{
    // Check for the proxy user
    $ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
}
else
{
    $ip = $_SERVER["REMOTE_ADDR"];
}
echo $ip;

I like this codesnippet:我喜欢这个代码片段:

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');
}

This is the method that I use, and it validates an IPv4 input:这是我使用的方法,它验证IPv4输入:

// Get user IP address
if ( isset($_SERVER['HTTP_CLIENT_IP']) && ! empty($_SERVER['HTTP_CLIENT_IP'])) {
    $ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif ( isset($_SERVER['HTTP_X_FORWARDED_FOR']) && ! empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
    $ip = (isset($_SERVER['REMOTE_ADDR'])) ? $_SERVER['REMOTE_ADDR'] : '0.0.0.0';
}

$ip = filter_var($ip, FILTER_VALIDATE_IP);
$ip = ($ip === false) ? '0.0.0.0' : $ip;

Well, this can be simply done by using the GLOBAL variable named as $_SERVER .好吧,这可以通过使用名为$_SERVERGLOBAL变量来简单地完成。

The $_SERVER is an array which has the attribute name REMOTE_ADDR . $_SERVER是一个具有属性名称REMOTE_ADDR的数组。

Just assign it like this:只需像这样分配它:

$userIp = $_SERVER['REMOTE_ADDR'];

Or use it directly like echo $_SERVER['REMOTE_ADDR'];或者直接使用echo $_SERVER['REMOTE_ADDR']; or echo ($_SERVER['REMOTE_ADDR']);echo ($_SERVER['REMOTE_ADDR']); . .

One of these :其中之一 :

    $ip = $_SERVER['REMOTE_ADDR'];
    $ip = $_SERVER['HTTP_CLIENT_IP'];
    $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
    $ip = $_SERVER['HTTP_X_FORWARDED'];
    $ip = $_SERVER['HTTP_FORWARDED_FOR'];
    $ip = $_SERVER['HTTP_FORWARDED'];

This function is compact and you can use it everywhere.这个功能很紧凑,你可以在任何地方使用它。 But!但!

Don't forget this!不要忘记这一点! In this type of functions or code blocks there is not a guarantee for recording the user's real IP address because some users can use a proxy or another secure gateway for be invisible or cannot tracking在此类功能或代码块中,无法保证记录用户的真实 IP 地址,因为某些用户可以使用代理或其他安全网关来隐藏或无法跟踪

PHP function: PHP函数:

function GetIP()
{
    if ( getenv("HTTP_CLIENT_IP") ) {
        $ip = getenv("HTTP_CLIENT_IP");
    } elseif ( getenv("HTTP_X_FORWARDED_FOR") ) {
        $ip = getenv("HTTP_X_FORWARDED_FOR");
        if ( strstr($ip, ',') ) {
            $tmp = explode(',', $ip);
            $ip = trim($tmp[0]);
        }
    } else {
        $ip = getenv("REMOTE_ADDR");
    }
    return $ip;
}

Usage:用法:

$IP = GetIP(); or directly GetIP();或直接GetIP();

The following function determine all possibilities and return the values in a comma separated format (ip, ip, etc.).以下函数确定所有可能性并以逗号分隔格式(ip、ip 等)返回值。

It has also an optional validation function as (first parameter that disabled by default) to validate the IP address against (private range and reserved range).它还有一个可选的验证功能(默认情况下禁用的第一个参数)来验证 IP 地址(私有范围和保留范围)。

<?php
echo GetClientIP(true);

function GetClientIP($validate = False) {
  $ipkeys = array(
  'REMOTE_ADDR',
  'HTTP_CLIENT_IP',
  'HTTP_X_FORWARDED_FOR',
  'HTTP_X_FORWARDED',
  'HTTP_FORWARDED_FOR',
  'HTTP_FORWARDED',
  'HTTP_X_CLUSTER_CLIENT_IP'
  );

  /*
  Now we check each key against $_SERVER if containing such value
  */
  $ip = array();
  foreach ($ipkeys as $keyword) {
    if (isset($_SERVER[$keyword])) {
      if ($validate) {
        if (ValidatePublicIP($_SERVER[$keyword])) {
          $ip[] = $_SERVER[$keyword];
        }
      }
      else{
        $ip[] = $_SERVER[$keyword];
      }
    }
  }

  $ip = ( empty($ip) ? 'Unknown' : implode(", ", $ip) );
  return $ip;
}

function ValidatePublicIP($ip){
  if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
    return true;
  }
  else {
    return false;
  }
}

Safe and warnings-aware snippet for getting the IP address:用于获取 IP 地址的安全且可感知警告的代码段:

$ip = filter_input(INPUT_SERVER, 'HTTP_CLIENT_IP', FILTER_VALIDATE_IP)
    ?: filter_input(INPUT_SERVER, 'HTTP_X_FORWARDED_FOR', FILTER_VALIDATE_IP)
    ?: $_SERVER['REMOTE_ADDR']
    ?? '0.0.0.0'; // Or other value fits "not defined" in your logic

试试这个:

 $_SERVER['REMOTE_ADDR'];

<?php
/**
 * Function to get the client ip address
 *
 * @return string The Ip address
 */
function getIp(): string {
    if (! empty($_SERVER['HTTP_CLIENT_IP'])) {
        return $_SERVER['HTTP_CLIENT_IP'];
    }

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

    return $_SERVER['REMOTE_ADDR'] ?? '?';
}

Even smaller更小

/**
 * Function to get the client ip address
 *
 * @return string The Ip address
 */
function getIp(): string {
    return $_SERVER['HTTP_CLIENT_IP'] ?? $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'] ?? '';
}

This function should work as expected此功能应按预期工作

function Get_User_Ip()
{
    $IP = false;
    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('HTTP_X_FORWARDED'))
    {
        $IP = getenv('HTTP_X_FORWARDED');
    }
    else if(getenv('HTTP_FORWARDED_FOR'))
    {
        $IP = getenv('HTTP_FORWARDED_FOR');
    }
    else if(getenv('HTTP_FORWARDED'))
    {
        $IP = getenv('HTTP_FORWARDED');
    }
    else if(getenv('REMOTE_ADDR'))
    {
        $IP = getenv('REMOTE_ADDR');
    }

    //If HTTP_X_FORWARDED_FOR == server ip
    if((($IP) && ($IP == getenv('SERVER_ADDR')) && (getenv('REMOTE_ADDR')) || (!filter_var($IP, FILTER_VALIDATE_IP))))
    {
        $IP = getenv('REMOTE_ADDR');
    }

    if($IP)
    {
        if(!filter_var($IP, FILTER_VALIDATE_IP))
        {
            $IP = false;
        }
    }
    else
    {
        $IP = false;
    }
    return $IP;
}

Just on this, and I'm surprised it hasn't been mentioned yet, is to get the correct IP addresses of those sites that are nestled behind the likes of CloudFlare infrastructure.就在这一点上,我很惊讶它还没有被提及,是获取那些位于 CloudFlare 基础设施后面的站点的正确 IP 地址。 It will break your IP addresses, and give them all the same value.它会破坏您的 IP 地址,并赋予它们相同的值。 Fortunately they have some server headers available too.幸运的是,他们也有一些可用的服务器标头。 Instead of me rewriting what's already been written, have a look here for a more concise answer, and yes, I went through this process a long while ago too.与其重写已经写好的东西,不如看看这里以获得更简洁的答案,是的,我很久以前也经历过这个过程。 https://stackoverflow.com/a/14985633/1190051 https://stackoverflow.com/a/14985633/1190051

Here's a simple one liner这是一个简单的单列

$ip = $_SERVER['HTTP_X_FORWARDED_FOR']?: $_SERVER['HTTP_CLIENT_IP']?: $_SERVER['REMOTE_ADDR'];

EDIT:编辑:

Above code may return reserved addresses (like 10.0.0.1), a list of addresses of all proxy servers on the way, etc. To handle these cases use the following code:上面的代码可能会返回保留地址(如 10.0.0.1)、途中所有代理服务器的地址列表等。要处理这些情况,请使用以下代码:

function valid_ip($ip) {
    // for list of reserved IP addresses, see https://en.wikipedia.org/wiki/Reserved_IP_addresses
    return $ip && substr($ip, 0, 4) != '127.' && substr($ip, 0, 4) != '127.' && substr($ip, 0, 3) != '10.' && substr($ip, 0, 2) != '0.' ? $ip : false;
}

function get_client_ip() {
    // using explode to get only client ip from list of forwarders. see https://en.wikipedia.org/wiki/X-Forwarded-For
    return
    @$_SERVER['HTTP_X_FORWARDED_FOR'] ? explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'], 2)[0] :
    @$_SERVER['HTTP_CLIENT_IP'] ? explode(',', $_SERVER['HTTP_CLIENT_IP'], 2)[0] :
    valid_ip(@$_SERVER['REMOTE_ADDR']) ?:
    'UNKNOWN';
}

echo get_client_ip();

How can I get the client IP address using PHP?如何使用PHP获取客户端IP地址?

I want to keep record of the user who logged into my website through his/her IP address.我想保留通过其IP地址登录到我的网站的用户的记录。

How can I get the client IP address using PHP?如何使用PHP获取客户端IP地址?

I want to keep record of the user who logged into my website through his/her IP address.我想保留通过其IP地址登录到我的网站的用户的记录。

In PHP the last option to get the public IP should always be $_SERVER["REMOTE_ADDR"] for way too many security reasons.在 PHP 中,由于太多的安全原因,获取公共 IP 的最后一个选项应该始终是$_SERVER["REMOTE_ADDR"]

Here is a workaround to get the validated IP address of the client.这是获取经过验证的客户端 IP 地址的解决方法。

public static function getPublicIP() : string
    {
        $realIP = "Invalid IP Address";

        $activeHeaders = [];

        $headers = [
            "HTTP_CLIENT_IP",
            "HTTP_PRAGMA",
            "HTTP_XONNECTION",
            "HTTP_CACHE_INFO",
            "HTTP_XPROXY",
            "HTTP_PROXY",
            "HTTP_PROXY_CONNECTION",
            "HTTP_VIA",
            "HTTP_X_COMING_FROM",
            "HTTP_COMING_FROM",
            "HTTP_X_FORWARDED_FOR",
            "HTTP_X_FORWARDED",
            "HTTP_X_CLUSTER_CLIENT_IP",
            "HTTP_FORWARDED_FOR",
            "HTTP_FORWARDED",
            "ZHTTP_CACHE_CONTROL",
            "REMOTE_ADDR" #this should be the last option
        ];

        #Find active headers
        foreach ($headers as $key)
        {
            if (array_key_exists($key, $_SERVER))
            {
                $activeHeaders[$key] = $_SERVER[$key];
            }
        }

         #Reemove remote address since we got more options to choose from
        if(count($activeHeaders) > 1)
        {
            unset($activeHeaders["REMOTE_ADDR"]);
        }

        #Pick a random item now that we have a secure way.
        $realIP = $activeHeaders[array_rand($activeHeaders)];

        #Validate the public IP
        if (filter_var($realIP, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4))
        {
            return $realIP;
        }

        return $realIP;
    }

As you can see here $_SERVER["REMOTE_ADDR"] is our last option to the IP.正如您在此处看到的,$_SERVER["REMOTE_ADDR"] 是我们对 IP 的最后一个选项。 After receiving the IP we also validate the IP to ensure quality and security.收到 IP 后,我们还会验证 IP 以确保质量和安全性。

How can I get the client IP address using PHP?如何使用PHP获取客户端IP地址?

I want to keep record of the user who logged into my website through his/her IP address.我想保留通过其IP地址登录到我的网站的用户的记录。

$_SERVER['REMOTE_ADDR'];

127.0.0.1 127.0.0.1

$getClientIP = $_SERVER['REMOTE_ADDR'];
echo $getClientIP;

127.0.0.1 127.0.0.1

If you don't like to use if-else/switch statements, then the following solution is for you.如果您不喜欢使用 if-else/switch 语句,那么以下解决方案适合您。

function get_client_ip()
{
    $fields = array(
        'HTTP_CF_CONNECTING_IP',
        'HTTP_X_SUCURI_CLIENTIP',
        'HTTP_CLIENT_IP',
        'HTTP_X_FORWARDED_FOR',
        'HTTP_X_FORWARDED',
        'HTTP_FORWARDED_FOR',
        'HTTP_FORWARDED',
        'REMOTE_ADDR',
        // more custom fields
    );

    foreach ($fields as $ip_field) {
        if (!empty($_SERVER[$ip_field])) {
            return $_SERVER[$ip_field];
        }
    }

    return null;
}

You can use below function您可以使用以下功能

function get_client_ip() {
    $ipaddress = '';
    if (isset($_SERVER['HTTP_CLIENT_IP']))
        $ipaddress = $_SERVER['HTTP_CLIENT_IP'];
    else if(isset($_SERVER['HTTP_X_FORWARDED_FOR']))
        $ipaddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
    else if(isset($_SERVER['HTTP_X_FORWARDED']))
        $ipaddress = $_SERVER['HTTP_X_FORWARDED'];
    else if(isset($_SERVER['HTTP_FORWARDED_FOR']))
        $ipaddress = $_SERVER['HTTP_FORWARDED_FOR'];
    else if(isset($_SERVER['HTTP_FORWARDED']))
        $ipaddress = $_SERVER['HTTP_FORWARDED'];
    else if(isset($_SERVER['REMOTE_ADDR']))
        $ipaddress = $_SERVER['REMOTE_ADDR'];
    else
        $ipaddress = 'UNKNOWN';
    return $ipaddress;
}

Like the following?像下面这样?

if (($ip=filter_input(INPUT_SERVER, 'REMOTE_ADDR', validate_ip)) === false or empty($ip)) {
    exit;
}
echo $ip;

PS附言

if (($ip=filter_input(INPUT_SERVER, 'REMOTE_ADDR', FILTER_VALIDATE_IP|FILTER_FLAG_NO_PRIV_RANGE|FILTER_FLAG_NO_RES_RANGE)) === false) {
    header('HTTP/1.0 400 Bad Request');
    exit;
}

All headers beginning with 'HTTP_' or 'X-' may be spoofed, respectively is user defined.所有以“HTTP_”或“X-”开头的标头都可能被欺骗,分别是用户定义的。 If you want to keep track, use cookies, etc.如果您想跟踪,请使用 cookie 等。

To get client IP Address, please use getenv("REMOTE_ADDR") .要获取客户端 IP 地址,请使用getenv("REMOTE_ADDR")

For example,例如,

$ip_address = getenv("REMOTE_ADDR");
echo $ip_address;

If you call your server using localhost, it will print out ::1 .如果您使用 localhost 调用服务器,它将打印出::1 So, please call your server using direct server ip address or domain.因此,请使用直接服务器 IP 地址或域呼叫您的服务器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM