Отправлять данные, которые заведомо не используются клиентом - это либо огромный косяк архитектора проекта, который такое захотел, либо косяк программиста, который поленился скрывать данные или выдает напрямую объект, например из БД, простая прокси бы полностью решила проблему;
Персональные данные отправлять без необходимости - не самая лучшая затея, потому что можно довольно легко организовать канал утечки, с последующим иском банку на пару млн рублей каждому пострадавшему ( Это не призыв, а лишь констатация факта того, что данные могут быть украдены );
HTTPS не дает 100% защиту, украсть данные можно внутри их сети, потому что там они так же передаются. По хорошему персональные данные без явного запроса клиента (хотя зачем они ему?) никуда не должны уходить с сервера, где они храняться;
При создании защищенных сетей не бывает такого понятия как "ну и что", вы обязаны ЛЮБЫЕ факторы взлома или утечки данных пресекать на корню. Если этого не делается, значит служба безопасности Раффайзена не работает вообще, хотя возможно, что их дурят, но тогда это вопрос об их компетентности.
На месте руководства Раффайзена стоило бы принять меры.
Если ты преступник (например наркоторговец), то для тебя очень выгодно, что можно безопасно передать деньги в другую страну.
Банковским переводом не удается почему-то это сделать, а перевезти несколько чемоданов — на таможке тормознут.
А зачем вам парсер, если на уровне лексера вы можете встроить анализ всех этих конструкций? Более того, давайте посмотрим на то, как работает препроцессор С++, он вообще не знает в плане вычислений условий, что существует С++, все вычисления производится только согласно стандарту препроцессора. Это вообще отдельная грамматика.
По сути процесс разбора для С++ выглядит примерно так:
1 Токенизировать файл, получить шаблонный файл препроцессора, состоящего из конструкций #if #else #end, #define, #udef, etc… Причем директивы можно вполне обрабатывать прямо вклинившись в токенизатор. Если есть инклюд, который вы не обработали, то ничто не мешает рекурсивно вызывать разбор файла внутри разбора файла. Это нужно, что бы потом можно было модифицировать набор дефайнов согласно шаблону. Т.е. вы проходите по хидеру, игнорируете все, что не относится к препроцессору, берете только дефайны, актуальные для текущего момента. При этом разбор заголовка ничем не будет отличаться от других файлов.
2 Преобразование потока токенов согласно шаблонным файлам, раскрыть макросы и управление препроцессором. В итоге если у вас были setup.h, setup.cpp, то на выходе будут те же самые файлы, только с раскрытыми макросами и удаленными полностью инструкциями препроцессора. Из setup.h в setup.cpp ничего не копируется и не вставляется.
3 Передать поток уже готовых токенов файла в парсер.
При таком подходе вам не надо все сливать в один файл (есть исключение для файлов inc, их токены надо именно что вставлять). Поэтому работать парсер будет на маленьком файле и ему не надо парсить каждый раз один и тот же набор деклараций из заголовков, потому что вы их проанализируете как отдельный файл.
И да, хочу еще раз отметить, что есть небольшая проблема с inc файлами, но обычно у них именно такое расширение, так что разрулить можно, хуже если умник какой-нибудь нарушает стандарты. Такой подход конечно же рискованный, но для SAST он вполне актуален. Экономит просто массу вычислительных ресурсов. Тем более что подать потом на парсер файлы в определенном порядке (а мы знаем все зависимости между файлами) труда вообще не составляет, не так ли?
Да это пример. И на ANTLR все языки пробую больше для понимания пределов работы этого фреймворка. Мне нужно знать его ограничения, так как некоторые вещи на нем реализовывать не просто быстрее и легче, но и оптимальнее.
Сделать самописный рекурсивный парсер вообще не представляется никакой проблемой. Более того, можно почти один в один скопировать код из roslyn на джаву и получить нужный мне парсер. Но зачем, если я уже знаю как оно будет работать с точностью до второго знака после запятой? =)
Если потребуется оптимизировать работу того или иного парсера/лексера — это можно будет сделать уже отдельно потом, потому что внутренний поток данных уже будет стандартом и от реализации никак не изменится.
Если я правильно понял, вы предлагаете хранить связь пользователь-роль-объект доступа в каждом ресурсном микросервисе, но всё равно, при наличии глобальных ролей, обращаться в сервис ролей за ними, тем самым делая на один запрос к какому-либо ресурсу 1 сетевой запрос и 1 запрос в БД.
Вам не всегда нужно делать дополнительный запрос в свою БД, при просмотре вы можете за один запрос и сущность получить и флаг видно/нет вытащить, а то и вовсе кинуть человеку 404, если он не должен видеть. Если же это изменение и нужно проверку сделать до, то что мешает держать кеш (Пользователь, Ресурс)=Булев? Он много памяти не скушает. Да и не особо он нужен в таком виде, необходимый запрос к БД выполняется за 0.002 ms, даже если у вас 10 000 000 строк в таблице. А зачем вам каждый раз для одного и того же пользователя получать его роли? В статье про то, что их нужно кешировать как раз и писалось.
Если хранить все доступы в одном месте, то возникает 2 проблемы:
Если идете по пути универсализации, то получается из БД вы вытаскиваете расчеты в приложение (нам же не просто доступ нужен, он может быть условный, временный или еще какой-то) — а это значит, что работать ваш ACL будет как старый пыльный пень, не надо так;
Если же пойдете по пути добавления функционала на каждый микросервис и подгонки БД под это дело, то у вас будет 100500 АПИ на каждый случай жизни и большущая команда разработки авторизации, когда хватило бы полтора инвалида для тех поддержки полностью завершенного и закрытого микросервиса ролевой модели, в который доработки если и потребуются, то на уровне "добавьте роль в БД на проме".
Роли пользователя не размазываются по микросервисам, потому что вы передаете только доступы. Попробуйте смотреть на предложенное с точки зрения иерархии микросервисов и разделения их на сегменты, что-то в духе — эта часть работы с проектами, эта с подбором персонала, а тут у нас обучение. Выкидываете один сегмент — все остальные работают как и работали, выпиливать или удалять из других БД вам ничего не нужно, потому что все лишнее уже само ушло. У вас система получается более гибкой и устойчивой к проблемам. Если у вас один огромный монолит под названием авторизация, то вы туда можете сколько угодно заливать ресурсов, но после определенного порога, вы уже кроме снижения производительности ничего не получите.
Если для вас мега-клиент, который должны использовать все против 1-2 клиента из N является более приемлимым вариантом, то я не знаю что вам тут сказать. Монолитом пахнет может? Это помимо того, что ваш мега-клиент будет стучаться в такой же мега-микросервис, в котором объединено много чего и вам нужна команда человек 40, просто что бы оно жило.
это от вас зависит. Сделать это можно как и раньше. Вы можете с сущностью вычислить доступ пользователя.
Что-то в таком духе (могут быть ошибки в синтаксисе):
SELECT new R(entity, (SELECT exists(*) FROM ppa where ppa.person = ?2 AND ppa.page = ?1 AND ppa.valid_until > CURRENT_TIMESTAMP ) FROM p WHERE p.id = ?1
Вам не нужно ничего перерасчитывать на фронте. Либо можно вовсе отдельную ручку сделать, отдаете туда идентификаторы статей/авторов, в ответ получаете карту ид=булев.
То же самое, если вам нужно массово получать статьи, но только те, на которые у вас есть подписки, к вашим условиям фильтрации добавляете дополнительное — существование записи ppa с нужными полями. Постгрес это делает очень быстро, особенно в случае индекс онли скана, что и должно быть.
Да, текст не хранится в токенах. По хорошему, если текст потом используется где-то (например в названиях переменных), то нужно обязательно пропускать через собственный интернер, что бы строки не дублировались в памяти, но вносить такое в токен не стоит.
Есть такое, но для регулярных выражений очень сложная семантика, поэтому выгоднее сделать простой валидатор, что бы не запускать процесс обработки вовсе, чем добавлять в кеш эту штуку.
Просто для примера, неправильно позиционированный предикат для регулярок JS заставляет в кэш попадать строки по 20-30 тысяч символов, просто потому что регулярка так парсится =) Это случается редко и скорее всего лишь во время жертвоприношения девственниц, но бабахает больно. Поэтому и не стал добавлять в список вредных советов ваш вариант, так как он ситуативен, даже несмотря на приведенный вами комментарий про DFA. Как уже говорил — DFA работает лишь в определенных границах, вне его пределов — превращается в шлак.
Статистику не собирал, слишком долго. Но в районе 2-3% должно дать, да. Правда есть одно но: изначально говорил, что еще можно 30-40% оптимизировать без злобных хаков то, что выложил =)
Ищите и думайте =) Итак уже безвозмездно выложил оптимизацию в 2-10 раз.
Отправлять данные, которые заведомо не используются клиентом - это либо огромный косяк архитектора проекта, который такое захотел, либо косяк программиста, который поленился скрывать данные или выдает напрямую объект, например из БД, простая прокси бы полностью решила проблему;
Персональные данные отправлять без необходимости - не самая лучшая затея, потому что можно довольно легко организовать канал утечки, с последующим иском банку на пару млн рублей каждому пострадавшему ( Это не призыв, а лишь констатация факта того, что данные могут быть украдены );
HTTPS не дает 100% защиту, украсть данные можно внутри их сети, потому что там они так же передаются. По хорошему персональные данные без явного запроса клиента (хотя зачем они ему?) никуда не должны уходить с сервера, где они храняться;
При создании защищенных сетей не бывает такого понятия как "ну и что", вы обязаны ЛЮБЫЕ факторы взлома или утечки данных пресекать на корню. Если этого не делается, значит служба безопасности Раффайзена не работает вообще, хотя возможно, что их дурят, но тогда это вопрос об их компетентности.
На месте руководства Раффайзена стоило бы принять меры.
Молитесь, кайтесь, питайтесь солнцем и надейтесь на доброго царя.
PS Это так не работает и вы должны были бы это знать как руководитель.
https://mvnrepository.com/artifact/org.ow2.asm/asm-tree
Не курьеры, а коммивояжеры.
Если ты преступник (например наркоторговец), то для тебя очень выгодно, что можно безопасно передать деньги в другую страну.
Банковским переводом не удается почему-то это сделать, а перевезти несколько чемоданов — на таможке тормознут.
Никто не сравнится с программистом, угрожающим проверять свои коммиты, перед тем как делать PR!
Тем не менее в режиме SLL со сверточной оптимизацией — творит чудеса =)
Спасибо за замечание, исправил.
После того обсуждения вопрос отложил пока, потому что бюджет времени на С# исчерпан пока что =)
Делу время, а потехе час.
А зачем вам парсер, если на уровне лексера вы можете встроить анализ всех этих конструкций? Более того, давайте посмотрим на то, как работает препроцессор С++, он вообще не знает в плане вычислений условий, что существует С++, все вычисления производится только согласно стандарту препроцессора. Это вообще отдельная грамматика.
По сути процесс разбора для С++ выглядит примерно так:
1 Токенизировать файл, получить шаблонный файл препроцессора, состоящего из конструкций #if #else #end, #define, #udef, etc… Причем директивы можно вполне обрабатывать прямо вклинившись в токенизатор. Если есть инклюд, который вы не обработали, то ничто не мешает рекурсивно вызывать разбор файла внутри разбора файла. Это нужно, что бы потом можно было модифицировать набор дефайнов согласно шаблону. Т.е. вы проходите по хидеру, игнорируете все, что не относится к препроцессору, берете только дефайны, актуальные для текущего момента. При этом разбор заголовка ничем не будет отличаться от других файлов.
2 Преобразование потока токенов согласно шаблонным файлам, раскрыть макросы и управление препроцессором. В итоге если у вас были setup.h, setup.cpp, то на выходе будут те же самые файлы, только с раскрытыми макросами и удаленными полностью инструкциями препроцессора. Из setup.h в setup.cpp ничего не копируется и не вставляется.
3 Передать поток уже готовых токенов файла в парсер.
При таком подходе вам не надо все сливать в один файл (есть исключение для файлов inc, их токены надо именно что вставлять). Поэтому работать парсер будет на маленьком файле и ему не надо парсить каждый раз один и тот же набор деклараций из заголовков, потому что вы их проанализируете как отдельный файл.
И да, хочу еще раз отметить, что есть небольшая проблема с inc файлами, но обычно у них именно такое расширение, так что разрулить можно, хуже если умник какой-нибудь нарушает стандарты. Такой подход конечно же рискованный, но для SAST он вполне актуален. Экономит просто массу вычислительных ресурсов. Тем более что подать потом на парсер файлы в определенном порядке (а мы знаем все зависимости между файлами) труда вообще не составляет, не так ли?
100% покрытие именно кода.
На 100% перебор всех альтернатив и вариантов комбинаций правил даже бейсика уйдет пара млн. человеколет.
Да это пример. И на ANTLR все языки пробую больше для понимания пределов работы этого фреймворка. Мне нужно знать его ограничения, так как некоторые вещи на нем реализовывать не просто быстрее и легче, но и оптимальнее.
Сделать самописный рекурсивный парсер вообще не представляется никакой проблемой. Более того, можно почти один в один скопировать код из roslyn на джаву и получить нужный мне парсер. Но зачем, если я уже знаю как оно будет работать с точностью до второго знака после запятой? =)
Если потребуется оптимизировать работу того или иного парсера/лексера — это можно будет сделать уже отдельно потом, потому что внутренний поток данных уже будет стандартом и от реализации никак не изменится.
Вам не всегда нужно делать дополнительный запрос в свою БД, при просмотре вы можете за один запрос и сущность получить и флаг видно/нет вытащить, а то и вовсе кинуть человеку 404, если он не должен видеть. Если же это изменение и нужно проверку сделать до, то что мешает держать кеш (Пользователь, Ресурс)=Булев? Он много памяти не скушает. Да и не особо он нужен в таком виде, необходимый запрос к БД выполняется за 0.002 ms, даже если у вас 10 000 000 строк в таблице. А зачем вам каждый раз для одного и того же пользователя получать его роли? В статье про то, что их нужно кешировать как раз и писалось.
Если хранить все доступы в одном месте, то возникает 2 проблемы:
Роли пользователя не размазываются по микросервисам, потому что вы передаете только доступы. Попробуйте смотреть на предложенное с точки зрения иерархии микросервисов и разделения их на сегменты, что-то в духе — эта часть работы с проектами, эта с подбором персонала, а тут у нас обучение. Выкидываете один сегмент — все остальные работают как и работали, выпиливать или удалять из других БД вам ничего не нужно, потому что все лишнее уже само ушло. У вас система получается более гибкой и устойчивой к проблемам. Если у вас один огромный монолит под названием авторизация, то вы туда можете сколько угодно заливать ресурсов, но после определенного порога, вы уже кроме снижения производительности ничего не получите.
Если для вас мега-клиент, который должны использовать все против 1-2 клиента из N является более приемлимым вариантом, то я не знаю что вам тут сказать. Монолитом пахнет может? Это помимо того, что ваш мега-клиент будет стучаться в такой же мега-микросервис, в котором объединено много чего и вам нужна команда человек 40, просто что бы оно жило.
это от вас зависит. Сделать это можно как и раньше. Вы можете с сущностью вычислить доступ пользователя.
Что-то в таком духе (могут быть ошибки в синтаксисе):
SELECT new R(entity, (SELECT exists(*) FROM ppa where ppa.person = ?2 AND ppa.page = ?1 AND ppa.valid_until > CURRENT_TIMESTAMP ) FROM p WHERE p.id = ?1
Вам не нужно ничего перерасчитывать на фронте. Либо можно вовсе отдельную ручку сделать, отдаете туда идентификаторы статей/авторов, в ответ получаете карту ид=булев.
То же самое, если вам нужно массово получать статьи, но только те, на которые у вас есть подписки, к вашим условиям фильтрации добавляете дополнительное — существование записи ppa с нужными полями. Постгрес это делает очень быстро, особенно в случае индекс онли скана, что и должно быть.
Никогда не променяю на ваши жалкие бусы.
Да, текст не хранится в токенах. По хорошему, если текст потом используется где-то (например в названиях переменных), то нужно обязательно пропускать через собственный интернер, что бы строки не дублировались в памяти, но вносить такое в токен не стоит.
Есть такое, но для регулярных выражений очень сложная семантика, поэтому выгоднее сделать простой валидатор, что бы не запускать процесс обработки вовсе, чем добавлять в кеш эту штуку.
Просто для примера, неправильно позиционированный предикат для регулярок JS заставляет в кэш попадать строки по 20-30 тысяч символов, просто потому что регулярка так парсится =) Это случается редко и скорее всего лишь во время жертвоприношения девственниц, но бабахает больно. Поэтому и не стал добавлять в список вредных советов ваш вариант, так как он ситуативен, даже несмотря на приведенный вами комментарий про DFA. Как уже говорил — DFA работает лишь в определенных границах, вне его пределов — превращается в шлак.
Статистику не собирал, слишком долго. Но в районе 2-3% должно дать, да. Правда есть одно но: изначально говорил, что еще можно 30-40% оптимизировать без злобных хаков то, что выложил =)
Ищите и думайте =) Итак уже безвозмездно выложил оптимизацию в 2-10 раз.
Тест токенизации файла размером 1,7 мб:
Как было — 5615 ms
Перенес за символ / предикат — 5440 ms
Небольшой выигрыш оказался :D
DELETED