PHP foreach banlist проверяет только последнюю строку файла - PullRequest
1 голос
/ 22 апреля 2020

У меня простой сайт, и я хотел бы иметь возможность запретить некоторым пользователям доступ к нему с помощью PHP. Вот метод, который я попробовал:

    $banlist = file('ipbans.txt');
    foreach ($banlist as $line)
    {
        if ($_SERVER['REMOTE_ADDR'] == $line) {
            die; 
        }
    }

К сожалению, этот подход приводит к завершению сценария (die) только для любого IP-адреса в последней строке ipbans.txt. В частности, я ожидаю, что каждое соединение с IP-адресом в любой строке ipbans.txt будет die, но это не так.

Мой веб-сайт слишком удален, чтобы на него можно было ориентироваться. количество преследований, и я не ожидаю, что когда-либо запретить столько IP-адресов. Таким образом, проблемы, которые могут возникнуть из-за наличия тысяч строк в ipbans.txt, не являются проблемой в этом случае. Однако, если есть технически более эффективный подход, который также легко реализовать, я открыт для его изучения. (Пока это все еще решение PHP - я не могу реализовать, например, .htaccess запреты.)

В любом случае, в чем причина такого поведения только в последней строке, и как можно Я это исправлю?

1 Ответ

2 голосов
/ 22 апреля 2020

Думаю, проблема в том, что метод PHP file включает в себя окончания строк для каждой строки. Обратите внимание на эту строку из документации :

Каждая строка в результирующем массиве будет содержать окончание строки, если не используется FILE_IGNORE_NEW_LINES.

Вам нужно использовать trim($line):

    $banlist = file('ipbans.txt');
    foreach ($banlist as $line)
    {
        if ($_SERVER['REMOTE_ADDR'] == trim($line)) {
            die; 
        }
    }

или FILE_IGNORE_NEW_LINES:

    $banlist = file('ipbans.txt', FILE_IGNORE_NEW_LINES);
    foreach ($banlist as $line)
    {
        if ($_SERVER['REMOTE_ADDR'] == $line) {
            die; 
        }
    }

Обновлен, чтобы включить объяснение

Когда вы читаете содержимое файла, он читает все символы, включая невидимые вещи, такие как окончания строк (EOF). Допустим, у вас был следующий файл:

xx.xx.xx.xx
yy.yy.yy.yy
zz.zz.zz.zz

Теперь давайте используем \n для представления символа окончания строки. Когда вы читаете это в массив, используя file, содержимое массива будет:

[
    "xx.xx.xx.xx\n",
    "yy.yy.yy.yy\n",
    "zz.zz.zz.zz"
]

Теперь, если удаленный адрес равен xx.xx.xx.xx, вы можете увидеть, что сравнение с xx.xx.xx.xx\n будет ложным , К счастью, использование trim($line) удалит любую новую строку или символы пробела в начале или конце строки. Вы также можете использовать флаг FILE_IGNORE_NEW_LINES, чтобы сообщить методу file обрезать каждую строку для вас при чтении ее в массив.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...