如何使用PHP获取客户端IP地址?

我想通过他/她的IP地址登录到我的网站的用户的记录。


当前回答

这里有一个简单的一行代码

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

编辑:

上面的代码可能会返回保留地址(如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();

其他回答

无论您做什么,请确保不要信任从客户端发送的数据。$_SERVER['REMOTE_ADDR']包含连接方的真实IP地址。这是你能找到的最可靠的值。

然而,它们可能在代理服务器的后面,在这种情况下,代理可能已经设置了$_SERVER['HTTP_X_FORWARDED_FOR'],但这个值很容易被欺骗。例如,它可以由没有代理的人设置,或者IP可以是来自代理后面LAN的内部IP。

这意味着如果您要保存$_SERVER['HTTP_X_FORWARDED_FOR'],请确保您也保存$_SERVER['REMOTE_ADDR']值。例如,将两个值保存在数据库的不同字段中。

如果要将IP保存为字符串到数据库,请确保至少有45个字符的空间。IPv6将继续存在,这些地址比旧的IPv4地址更大。

(请注意,IPv6通常最多使用39个字符,但IPv4地址也有一个特殊的IPv6符号,其完整形式最多可达45个字符。所以如果你知道你在做什么,你可以使用39个字符,但如果你只是想设置并忘记它,请使用45)。

互联网背后有不同类型的用户,因此我们希望从不同的部分捕获IP地址。这些都是:

1. $ _SERVER [' REMOTE_ADDR '] - 其中包含客户端的真实IP地址。这是您可以从用户那里找到的最可靠的值。

2. $ _SERVER [' REMOTE_HOST '] - 这将获取用户正在查看当前页面的主机名。但是要使这个脚本工作,必须在httpd.conf中配置主机名查找。

3.$ _SERVER [' HTTP_CLIENT_IP '] - 当用户来自共享Internet服务时,这将获取IP地址。

4. $_SERVER['HTTP_X_FORWARDED_FOR'] -这将从用户获取IP地址时,他/她是后面的代理。

所以我们可以用下面这个组合函数从不同位置观看的用户那里得到真实的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;
}

像下面这样?

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

所有以'HTTP_'或'X-'开头的报头都可能被欺骗,分别由用户定义。如果你想要跟踪,可以使用cookie等。

在这一点上,我很惊讶它还没有被提及,就是获得那些位于CloudFlare基础设施后面的网站的正确IP地址。它将打破你的IP地址,并给他们所有相同的值。 幸运的是,他们也有一些可用的服务器头。 与其我重写已经写过的东西,不如看看这里的一个更简洁的答案,是的,我很久以前也经历过这个过程。 https://stackoverflow.com/a/14985633/1190051


<?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'] ?? '?';
}

更小的

/**
 * 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'] ?? '';
}