Мда, вынос условий в отдельный цикл — красиво. Экономит 7 миллисекунд на 50К файлов на моей машине.
И по потреблению CPU/память, похоже, что действительно самый оптимальный вариант.
У substr нет выигрыша в скорости, но удвоенный расход памяти, а ls -m через system() и вовсе оказался в 4 раза медленнее.
С кэшированием в мемкешеде, правда, по скорости получается в 6 раз быстрее, 10 мс всего, но это лишняя память (для всех просмотренных каталогов!) плюс для однопользовательского файлменеджера это вообще не вариант, скорее всего.
Но я всё равно такой экономией на спичках заниматься не стал бы =)
Но если б меня эти миллисекунды прям так запарили, то точки на сервере я бы не стал отрезать вовсе, а так и отправил в браузер. Там цикл на порядки меньше и эта проверка погоды уже не сделает, как мне кажется. Но клиентская сторона — единственное, что я не пробовал профилировать, так что могу здесь ошибаться =)
Имена файлов — 32 байта, но 32-битная система, так что расход памяти такой же — 1,6М
Вы допускаете очень распространённую ошибку, о которой я говорил на конференции:
Ставя собаку, РНР программист полагает, что ошибка бывает только одного типа.
Это неверно, и на этом заблуждении было потрачено впустую немало человеко-часов.
Для таких исключительных случаев лучше использовать исключения —
Ставить трай и отлавливать ошибку в кетче.
Ошибку ПРОВЕРЯТЬ, та ли это, которую мы ждём.
Если та — продолжаем выполнение программы.
Если нет — выбрасываем эту же ошибку снова, через trigger_error
Для этого надо переопределять error_handler, разумеется, но это и так везде сделано, мне кажется.
Разумеется, это не слишком красиво, и такой кривизны лучше избегать, меняя логику программы.
Скажем, сама проверка «сериализована ли строка» говорит о непродуманности логики программы. Хорошая программа всегда знает, какого рода данные ожидаются на вход.
Но в любом случае, ставя собаку всегда следует помнить, что ошибки бывают РАЗНЫЕ, а не только те, про которые мы знаем и которые ждём ;)
1. Вы пропустили контекст.
Речь не о предупреждениях РНР, а об «ошибках, обнаруженных ХипХопом».
Я в комментарии ниже приводил слова Расмуса о том, что статический анализатор выполняет в 10 раз больше работы, чем обычный интерпретатор, и ошибки, которые он выдаёт, не отлавливаются обычным PHP. Это получается что-то вроде super-strict mode.
К примеру, Хипхоп отлавливает код, который никогда не выполняется, или передачу функции большего количества параметров, чем было объявлено. PHP на это не обращает внимания, а хипхоп — ругается.
2. Отключая ошибки «на финальной публикации» вы допускаете большую ошибку. На боевом сервере они нужны не меньше, чем на тестовом. Отключен должен быть только вывод на экран, разумеется. А сами «нотисы/варнинги/ерроры» должны быть включены так же как на тестовом — по максимуму, и писаться в лог.
Насколько я помню, к ограничением хипхопа относится запрет на использование евала.
По поводу обнаруженных ошибок — и то и другое. Отсутствующий инклюд — это явная ошибка. Лишний параметр при вызове функции — возможная.
Сломанного билда не будет, поскольку тестирование делается перед коммитом.
Варнингов на [плохом] коде будет много, да. Расмус так и сказал — «кто хочет затроллить багтрекер любого опенсорс проекта, может натравливать анализатор хипхопа и писать тикеты десятками. „
Собственно, чтобы не было много предупреждений — нужно писать чистый код. И начинать тестировать его сразу, а не после того, как написано 100500 строк.
Скажем, во время презентации Расмус нашёл место в Вордпрессе, где в случае ошибки при fopen()… делался fclose()! И это очевидный говнокод.
Собственно, многие забывают, что куча варнингов “на которые всем пофиг» — это не проблема анализатора, это проблема кода.
Строго говоря, компиляции там не происходит.
Расмус это подчеркнул — «на компиляцию ушло бы минут 20 на моём ноутбуке» — сказал он — «но статический анализ происходит так быстро, что его можно вешать на коммит».
Но смыслу сказанного вами это не противоречит: опять же, со слов Расмуса, «статический анализатор должен сделать в 10 раз больше вещей, чем обычный парсер РНР». Задача анализатора — отследить все возможные косяки до компиляции.
С другой стороны, ничто не мешает ту же самую функциональность реализовать силами IDE — ведь, теоретически, ide может отследить потерянный инклюд, лишние аргументы функции и многое другое. Вопрос — насколько полно и точно они это делают.
По пунктам моего комментария выше.
В нём объясняется, почему твои «подробно расписанные сообщения» не имеют никакого отношения к вопросу, который был тебе задан.
Возразить на эти объяснения тебе нечего.
Что, с одной стороны жаль — я ожидал большей адекватности от собеседника — но с другой сильно облегчает мою задачу: мне больше не нужно тратить своё время.
Да какая разница, куда «кидать» сессию?
К защите от CSRF это не имеет отношения.
Сессия может прекрасно жить и в файлах, если «несколько доменов»находятся на одном физическом сервере. Может «кидаться» в мемкеш даже если домен только один. может в базу. Но к теме вопроса это не имеет ни малейшего отношения.
В общем, чтобы определиться.
1. Сессия тут вообще не при чём. Она у нас уже есть, и как она реализована — нам не важно.
2. В куках токен хранить не имеет смысла:
— если использовать его по прямому назначению — проверяя его наличие при обработке формы — то для защиты от CSRF это не поможет.
— просто класть в куки, «а потом забирать, если что» так же бессмысленно: злоумышленник преспокойно получит токен себе и впишет его в форму. Смысл имееет только пара «токен в сессии — токен в коде формы»
Так я до сих пор и не увидел примера ситуации, в которой сохраняемый одновременно и в сессии, и в форме токен «не особо помогает при CSRF.»
А пользовательские-то файлы здесь при чём? Мы же, вроде, говорили о защите файлов приложения/сервера?
Я не очень понял сценарий атаки с пользовательской папкой.
Нет-нет, токен в куках — это не «недостаток», это просто фейл.
Куки в принципе не могут защитить от CSRF, исходя из самой природы этой атаки: зачем красть куку, если браузер сам её отправит? :)
Не вижу, кстати, причины, по которой токен в коде формы не будет работать на мультидоменной конфигурации. Чем токен отличается от любой другой сессионной переменной?
Если у нас есть требующее сквозной авторизации приложение, работающее на нескольких доменах, то сессия по определению должна работать на них на всех.
Ну, я-то как раз наоборот пишу, что белый список здесь не нужен.
Предложенного мной универсального решения (динамическим может быть только имя файла, и оно соответствующим образом валидируется, а каталог же строится автоматически исходя из логики приложения) должно быть достаточно.
Для случаев, когда приложение занимается именно просмотром физических каталогов по запросам пользователя, подойдёт описанное выше решение-аналог open_basedir.
Да, верно. Только речь не только об урлах, а о динамике в запросах вообще.
И в качестве примера ключевого слова я бы привёл скорее такие, как OR или DESC.
:)
Как раз о снижении нагрузки и идёт речь.
Вы забываете, что здесь используется чёрный список.
То есть, он по определению не может охватить все «паразитные» запросы.
При этом мы можем предположить, что если с определённого IP пришёл запрос на /etc/passwd, то в течение ближайшего (условно) часа от него вряд ли можно ожидать покупок, и с чистой совестью можно банить.
А отсекать 1 запрос по известному системе паттерну и пропускать 99 столь же «полезных», но валидных с точки зрения файрволла — смысла немного.
Впрочем, вы правы. Если у вас посещаемость не 200 человек в сутки, хакерская активность не слишком заметна на фоне обычного трафика.
А можно, всё-таки, своими словами?
«Другие ситуации», которые я там увидел — это другие типы атак, man in the middle, например.
Но подтверждения фразе «токен тоже не особо помогает при CSRF» я там не увидел.
Мда, видимо, правила всё-таки не настолько очевидные, если для SQL совсем забыты идентификаторы и ключевые слова :)
RFI/LFI — remote/local file execution, directory traversal — переход на уровень выше. Чтение и вывод файлов, в общем.
Мне кажется, что правила для работы с файлами могут быть куда проще, для этого даже белый список не нужен.
Я вообще всегда стараюсь упрощать наборы правил, а то длинные соблюдать сложно :)
Что интересно — правила разработки отличаются от правил фильтрации. Первые одновременно и проще, и надёжнее. Именно этим фактом вызвано моё скептическое отношение к таким файрволлам.
Если, скажем, фильтратору важно знать, что в переданном запросе есть точки, то он даже невинные зарубит, а обращение, скажем, к абсолютному пути прекрасно пропустит — там точек нету ведь! :)
А разработчик может просто выделить в переданном параметре имя файла, каталог сгенерировать самому и проверить получившийся путь на читаемость.
И по потреблению CPU/память, похоже, что действительно самый оптимальный вариант.
У substr нет выигрыша в скорости, но удвоенный расход памяти, а ls -m через system() и вовсе оказался в 4 раза медленнее.
С кэшированием в мемкешеде, правда, по скорости получается в 6 раз быстрее, 10 мс всего, но это лишняя память (для всех просмотренных каталогов!) плюс для однопользовательского файлменеджера это вообще не вариант, скорее всего.
Но я всё равно такой экономией на спичках заниматься не стал бы =)
Но если б меня эти миллисекунды прям так запарили, то точки на сервере я бы не стал отрезать вовсе, а так и отправил в браузер. Там цикл на порядки меньше и эта проверка погоды уже не сделает, как мне кажется. Но клиентская сторона — единственное, что я не пробовал профилировать, так что могу здесь ошибаться =)
Имена файлов — 32 байта, но 32-битная система, так что расход памяти такой же — 1,6М
Ставя собаку, РНР программист полагает, что ошибка бывает только одного типа.
Это неверно, и на этом заблуждении было потрачено впустую немало человеко-часов.
Для таких исключительных случаев лучше использовать исключения —
Ставить трай и отлавливать ошибку в кетче.
Ошибку ПРОВЕРЯТЬ, та ли это, которую мы ждём.
Если та — продолжаем выполнение программы.
Если нет — выбрасываем эту же ошибку снова, через trigger_error
Для этого надо переопределять error_handler, разумеется, но это и так везде сделано, мне кажется.
Разумеется, это не слишком красиво, и такой кривизны лучше избегать, меняя логику программы.
Скажем, сама проверка «сериализована ли строка» говорит о непродуманности логики программы. Хорошая программа всегда знает, какого рода данные ожидаются на вход.
Но в любом случае, ставя собаку всегда следует помнить, что ошибки бывают РАЗНЫЕ, а не только те, про которые мы знаем и которые ждём ;)
Речь не о предупреждениях РНР, а об «ошибках, обнаруженных ХипХопом».
Я в комментарии ниже приводил слова Расмуса о том, что статический анализатор выполняет в 10 раз больше работы, чем обычный интерпретатор, и ошибки, которые он выдаёт, не отлавливаются обычным PHP. Это получается что-то вроде super-strict mode.
К примеру, Хипхоп отлавливает код, который никогда не выполняется, или передачу функции большего количества параметров, чем было объявлено. PHP на это не обращает внимания, а хипхоп — ругается.
2. Отключая ошибки «на финальной публикации» вы допускаете большую ошибку. На боевом сервере они нужны не меньше, чем на тестовом. Отключен должен быть только вывод на экран, разумеется. А сами «нотисы/варнинги/ерроры» должны быть включены так же как на тестовом — по максимуму, и писаться в лог.
По поводу обнаруженных ошибок — и то и другое. Отсутствующий инклюд — это явная ошибка. Лишний параметр при вызове функции — возможная.
Сломанного билда не будет, поскольку тестирование делается перед коммитом.
Варнингов на [плохом] коде будет много, да. Расмус так и сказал — «кто хочет затроллить багтрекер любого опенсорс проекта, может натравливать анализатор хипхопа и писать тикеты десятками. „
Собственно, чтобы не было много предупреждений — нужно писать чистый код. И начинать тестировать его сразу, а не после того, как написано 100500 строк.
Скажем, во время презентации Расмус нашёл место в Вордпрессе, где в случае ошибки при fopen()… делался fclose()! И это очевидный говнокод.
Собственно, многие забывают, что куча варнингов “на которые всем пофиг» — это не проблема анализатора, это проблема кода.
Расмус это подчеркнул — «на компиляцию ушло бы минут 20 на моём ноутбуке» — сказал он — «но статический анализ происходит так быстро, что его можно вешать на коммит».
Но смыслу сказанного вами это не противоречит: опять же, со слов Расмуса, «статический анализатор должен сделать в 10 раз больше вещей, чем обычный парсер РНР». Задача анализатора — отследить все возможные косяки до компиляции.
С другой стороны, ничто не мешает ту же самую функциональность реализовать силами IDE — ведь, теоретически, ide может отследить потерянный инклюд, лишние аргументы функции и многое другое. Вопрос — насколько полно и точно они это делают.
В нём объясняется, почему твои «подробно расписанные сообщения» не имеют никакого отношения к вопросу, который был тебе задан.
Возразить на эти объяснения тебе нечего.
Что, с одной стороны жаль — я ожидал большей адекватности от собеседника — но с другой сильно облегчает мою задачу: мне больше не нужно тратить своё время.
Вот и славненько.
К защите от CSRF это не имеет отношения.
Сессия может прекрасно жить и в файлах, если «несколько доменов»находятся на одном физическом сервере. Может «кидаться» в мемкеш даже если домен только один. может в базу. Но к теме вопроса это не имеет ни малейшего отношения.
В общем, чтобы определиться.
1. Сессия тут вообще не при чём. Она у нас уже есть, и как она реализована — нам не важно.
2. В куках токен хранить не имеет смысла:
— если использовать его по прямому назначению — проверяя его наличие при обработке формы — то для защиты от CSRF это не поможет.
— просто класть в куки, «а потом забирать, если что» так же бессмысленно: злоумышленник преспокойно получит токен себе и впишет его в форму. Смысл имееет только пара «токен в сессии — токен в коде формы»
Так я до сих пор и не увидел примера ситуации, в которой сохраняемый одновременно и в сессии, и в форме токен «не особо помогает при CSRF.»
Я не очень понял сценарий атаки с пользовательской папкой.
Куки в принципе не могут защитить от CSRF, исходя из самой природы этой атаки: зачем красть куку, если браузер сам её отправит? :)
Не вижу, кстати, причины, по которой токен в коде формы не будет работать на мультидоменной конфигурации. Чем токен отличается от любой другой сессионной переменной?
Если у нас есть требующее сквозной авторизации приложение, работающее на нескольких доменах, то сессия по определению должна работать на них на всех.
Предложенного мной универсального решения (динамическим может быть только имя файла, и оно соответствующим образом валидируется, а каталог же строится автоматически исходя из логики приложения) должно быть достаточно.
Для случаев, когда приложение занимается именно просмотром физических каталогов по запросам пользователя, подойдёт описанное выше решение-аналог open_basedir.
И в качестве примера ключевого слова я бы привёл скорее такие, как OR или DESC.
Как раз о снижении нагрузки и идёт речь.
Вы забываете, что здесь используется чёрный список.
То есть, он по определению не может охватить все «паразитные» запросы.
При этом мы можем предположить, что если с определённого IP пришёл запрос на /etc/passwd, то в течение ближайшего (условно) часа от него вряд ли можно ожидать покупок, и с чистой совестью можно банить.
А отсекать 1 запрос по известному системе паттерну и пропускать 99 столь же «полезных», но валидных с точки зрения файрволла — смысла немного.
Впрочем, вы правы. Если у вас посещаемость не 200 человек в сутки, хакерская активность не слишком заметна на фоне обычного трафика.
«Другие ситуации», которые я там увидел — это другие типы атак, man in the middle, например.
Но подтверждения фразе «токен тоже не особо помогает при CSRF» я там не увидел.
RFI/LFI — remote/local file execution, directory traversal — переход на уровень выше. Чтение и вывод файлов, в общем.
Мне кажется, что правила для работы с файлами могут быть куда проще, для этого даже белый список не нужен.
Я вообще всегда стараюсь упрощать наборы правил, а то длинные соблюдать сложно :)
Что интересно — правила разработки отличаются от правил фильтрации. Первые одновременно и проще, и надёжнее. Именно этим фактом вызвано моё скептическое отношение к таким файрволлам.
Если, скажем, фильтратору важно знать, что в переданном запросе есть точки, то он даже невинные зарубит, а обращение, скажем, к абсолютному пути прекрасно пропустит — там точек нету ведь! :)
А разработчик может просто выделить в переданном параметре имя файла, каталог сгенерировать самому и проверить получившийся путь на читаемость.
Наоборот, исходил из того, что читателям хабра эти правила известны.
Можно про CSRF своими словами или ссылкой?