Что самый точный путь состоит в том, чтобы получить корректный IP-адрес пользователя в PHP?

Вы можете использовать итеративный и рекурсивный подход, передав массив source для нового label и массив target для конечного результата с детьми.

Принимая вышеуказанный требуемый формат, без свойства children в самом внутреннем объекте, этот подход принимает в качестве цели объект с дочерними элементами. Редукционная часть для генерации новой структуры данных принимает только объекты в качестве возвращаемого значения и создает children при необходимости.

var data = { entity: { entityLabel: "Virtual Reality", parent: [{ entity: { entityLabel: "Artificial Intelligence", parent: [{ entity: { entityLabel: "Information Technology" } }] } }] } },
    result = [];

[data].forEach(function iter(source, target) {
    return function ({ entity: { entityLabel, parent } }) {
        source = [entityLabel, ...source];
        if (parent) return parent.forEach(iter(source, target));
        source.reduce((t, label) => {
            var temp = (t.children = t.children || []).find(o => o.label === label);
            if (!temp) {
                t.children.push(temp = { label });
            }
            return temp;
        }, target);
    }
}([], { children: result }));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

280
задан Peter Mortensen 15 April 2014 в 20:53
поделиться

8 ответов

[

][]Вот более короткий и чистый способ получить IP-адрес:[][

] [
function get_ip_address(){
    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 (explode(',', $_SERVER[$key]) as $ip){
                $ip = trim($ip); // just to be safe

                if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false){
                    return $ip;
                }
            }
        }
    }
}
] [

]Надеюсь, это поможет! [

] [
] [

]Ваш код, кажется, уже довольно полный, я не вижу в нем никаких возможных ошибок (кроме обычных IP-оговорок), я бы изменил функцию []validate_ip()[], чтобы полагаться на расширение фильтра, хотя:[

] [
public function validate_ip($ip)
{
    if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) === false)
    {
        return false;
    }

    self::$ip = sprintf('%u', ip2long($ip)); // you seem to want this

    return true;
}
] [

]Также ваш фрагмент []HTTP_X_FORWARDED_FOR[] можно упростить следующим образом:[

] [
// check for IPs passing through proxies
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR']))
{
    // check if multiple ips exist in var
    if (strpos($_SERVER['HTTP_X_FORWARDED_FOR'], ',') !== false)
    {
        $iplist = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);

        foreach ($iplist as $ip)
        {
            if ($this->validate_ip($ip))
                return $ip;
        }
    }

    else
    {
        if ($this->validate_ip($_SERVER['HTTP_X_FORWARDED_FOR']))
            return $_SERVER['HTTP_X_FORWARDED_FOR'];
    }
}
] [

]К этому:[

] [
// check for IPs passing through proxies
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR']))
{
    $iplist = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);

    foreach ($iplist as $ip)
    {
        if ($this->validate_ip($ip))
            return $ip;
    }
}
] [

]Вы также можете захотеть проверить IPv6-адреса.[

].
240
ответ дан 23 November 2019 в 02:00
поделиться

Я удивлен, что никто не упомянул filter_input, таким образом, вот ответ Alix Axel сжат к короткому:

function get_ip_address(&$keys = ['HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'HTTP_CLIENT_IP', 'REMOTE_ADDR'])
{
    return empty($keys) || ($ip = filter_input(INPUT_SERVER, array_pop($keys), FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE))? $ip : get_ip_address($keys);
}
0
ответ дан 23 November 2019 в 02:00
поделиться

Вы в значительной степени ответили на свой вопрос! :)

function getRealIpAddr() {
    if(!empty($_SERVER['HTTP_CLIENT_IP']))   //Check IP address from shared Internet
    {
        $IPaddress = $_SERVER['HTTP_CLIENT_IP'];
    }
    elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR']))   //To check IP address is passed from the proxy
    {
        $IPaddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
    }
    else
    {
        $IPaddress = $_SERVER['REMOTE_ADDR'];
    }
    return $IPaddress;
}

Источник

-1
ответ дан 23 November 2019 в 02:00
поделиться

Однако даже в этом случае получение реального IP-адреса пользователя будет ненадежным. Все, что им нужно сделать, это использовать анонимный прокси-сервер (тот, который не учитывает заголовки для http_x_forwarded_for, http_forwarded и т. Д.), И все, что вы получите, это IP-адрес их прокси-сервера.

Затем вы можете увидеть, есть ли список IP-адресов прокси-сервера, которые являются анонимными, но нет никакого способа быть уверенным, что они также на 100% точны, и самое большее, что он сделает, - это сообщить вам, что это прокси-сервер. А если кто-то сообразителен, он может подделать заголовки для пересылки HTTP.

Допустим, мне не нравится местный колледж. Я выясняю, какие IP-адреса они зарегистрировали, и получаю их IP-адреса, запрещенные на вашем сайте, делая плохие вещи, потому что я понимаю, что вы уважаете пересылки HTTP. Список бесконечен.

Тогда есть, как вы догадались, внутренние IP-адреса, такие как сеть колледжа, о которой я упоминал ранее. Многие используют формат 10.xxx. Итак, все, что вы должны знать, это то, что он был перенаправлен для общей сети.

Тогда я не буду вдаваться в подробности, но динамические IP-адреса больше являются способом широкополосной связи. Так. Даже если вы получите IP-адрес пользователя, ожидайте, что он изменится самое позднее через 2–3 месяца.

10
ответ дан 23 November 2019 в 02:00
поделиться

Мы используем:

/**
 * Get the customer's IP address.
 *
 * @return string
 */
public function getIpAddress() {
    if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
        return $_SERVER['HTTP_CLIENT_IP'];
    } else if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
        return trim($ips[count($ips) - 1]);
    } else {
        return $_SERVER['REMOTE_ADDR'];
    }
}

Взрыв на HTTP_X_FORWARDED_FOR произошел из-за странных проблем с обнаружением IP-адресов при использовании Squid.

.
7
ответ дан 23 November 2019 в 02:00
поделиться

Самый большой вопрос - для каких целей?

Ваш код почти настолько полон, насколько это возможно - но я вижу, что если вы заметили, что выглядит как добавленный заголовок прокси, вы используете INSTEAD CLIENT_IP, однако, если вы хотите, чтобы эта информация была использована в целях аудита, тогда будьте предупреждены - ее очень легко подделать.

Конечно, вы никогда не должны использовать IP-адреса для любого вида аутентификации - даже эти адреса могут быть подделаны.

Вы можете получить лучшее измерение клиентского ip-адреса, выдавливая флеш или java-апплет, который соединяется с сервером через неhttp-порт (что, таким образом, выявит прозрачные прокси или случаи, когда вставленные прокси-заголовки ложны - но имейте в виду, что, когда клиент может ТОЛЬКО соединиться через web-прокси или исходящий порт заблокирован, соединение с апплета не будет установлено.

C.

2
ответ дан 23 November 2019 в 02:00
поделиться
/**
 * Sanitizes IPv4 address according to Ilia Alshanetsky's book
 * "php|architect?s Guide to PHP Security", chapter 2, page 67.
 *
 * @param string $ip An IPv4 address
 */
public static function sanitizeIpAddress($ip = '')
{
if ($ip == '')
    {
    $rtnStr = '0.0.0.0';
    }
else
    {
    $rtnStr = long2ip(ip2long($ip));
    }

return $rtnStr;
}

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

/**
 * Returns the sanitized HTTP_X_FORWARDED_FOR server variable.
 *
 */
public static function getXForwardedFor()
{
if (isset($_SERVER['HTTP_X_FORWARDED_FOR']))
    {
    $rtnStr = $_SERVER['HTTP_X_FORWARDED_FOR'];
    }
elseif (isset($HTTP_SERVER_VARS['HTTP_X_FORWARDED_FOR']))
    {
    $rtnStr = $HTTP_SERVER_VARS['HTTP_X_FORWARDED_FOR'];
    }
elseif (getenv('HTTP_X_FORWARDED_FOR'))
    {
    $rtnStr = getenv('HTTP_X_FORWARDED_FOR');
    }
else
    {
    $rtnStr = '';
    }

// Sanitize IPv4 address (Ilia Alshanetsky):
if ($rtnStr != '')
    {
    $rtnStr = explode(', ', $rtnStr);
    $rtnStr = self::sanitizeIpAddress($rtnStr[0]);
    }

return $rtnStr;
}

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

/**
 * Returns the sanitized REMOTE_ADDR server variable.
 *
 */
public static function getRemoteAddr()
{
if (isset($_SERVER['REMOTE_ADDR']))
    {
    $rtnStr = $_SERVER['REMOTE_ADDR'];
    }
elseif (isset($HTTP_SERVER_VARS['REMOTE_ADDR']))
    {
    $rtnStr = $HTTP_SERVER_VARS['REMOTE_ADDR'];
    }
elseif (getenv('REMOTE_ADDR'))
    {
    $rtnStr = getenv('REMOTE_ADDR');
    }
else
    {
    $rtnStr = '';
    }

// Sanitize IPv4 address (Ilia Alshanetsky):
if ($rtnStr != '')
    {
    $rtnStr = explode(', ', $rtnStr);
    $rtnStr = self::sanitizeIpAddress($rtnStr[0]);
    }

return $rtnStr;
}

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

/**
 * Returns the sanitized remote user and proxy IP addresses.
 *
 */
public static function getIpAndProxy()
{
$xForwarded = self::getXForwardedFor();
$remoteAddr = self::getRemoteAddr();

if ($xForwarded != '')
    {
    $ip    = $xForwarded;
    $proxy = $remoteAddr;
    }
else
    {
    $ip    = $remoteAddr;
    $proxy = '';
    }

return array($ip, $proxy);
}
-6
ответ дан 23 November 2019 в 02:00
поделиться

Мне интересно, возможно ли вы, возможно, вы должны повторять взорванные в обратном порядке http_x_forwarded_for в обратном порядке, поскольку мой опыт был, что IP-адрес пользователя заканчивается в конце списка, разделенного запятыми, поэтому начиная с начала заголовка, У вас больше шансов получить IP-адрес одного из возвращенных прокси, что может по-прежнему разрешить угон для сеанса, так как многие пользователи могут пройти через этот прокси.

0
ответ дан 23 November 2019 в 02:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: