Система модулей Java Platform - в чем смысл защиты?
Я прочитал одно из преимуществ JPMS - лучшая инкапсуляция (все ограничено, если явно не открыто).
Но у меня есть вопрос: что мешает программисту заменить module-info.class
в сторонний модуль JAR и экспортировать все пакеты, или даже сделать open
модуль, так что все доступно через отражение (в том числе private
члены).
Является ли JPMS чем-то, что действительно может помочь скрыть внутренний код, или это похоже на Java 8 и более ранние версии: все доступно через Reflection API, даже private
члены (просто дополнительный шаг, необходимый для Java 9, чтобы открыть модуль)?
1 ответ
Я думаю, будет справедливым сказать, что защита в смысле кода безопасности / защиты от несанкционированного доступа не является основной целью JPMS.
Если вмешательство все еще возможно, все еще очень важно иметь возможность определять, играет ли данное приложение по правилам (или, в какой степени правила были смягчены).
Одна очевидная мотивация заключается в том, чтобы более или менее осторожно подталкивать разработчиков к созданию "хорошего, модульного" кода. Постепенно "лучший" код все еще "лучше", чем "плохой" код. Необходимость принять дополнительные меры в некоторых случаях станет причиной противостоять искушению.
Менее очевидной мотивацией является поддержка расширенного модульного анализа потока во время выполнения, что будет полезно для тех оптимизаций, которые JIT может безопасно выполнить.
Много лет назад я придумал термин "постепенная инкапсуляция" для обозначения метода и технологии, которые обеспечивают "столько инкапсуляции, сколько вы можете себе позволить", не меньше, но, что важно, не больше, чем вы можете себе позволить (создание идеальной инкапсуляции имеет свою цену). Набор параметров командной строки JPMS для настройки модульности можно рассматривать как набор инструментов для точного объявления исключений, когда вы не можете позволить себе совершенную инкапсуляцию (по одной из различных возможных причин). Подделка jar-файлов, конечно, возможна, но она также обнаруживается, если оригинал подписан. Во всем этом очень важно быть "честным", даже если вы не можете быть "идеальным".
(Все термины в кавычках явно относятся к делу).
Существует фундаментальная разница между исправлением сохраненного модуля и использованием Reflection для доступа к закрытым членам без изменения сохраненных классов.
Как правило, абсолютной безопасности нет. Безопасность всегда зависит от сложности работы злоумышленника. В лучшем случае успешная атака требует гораздо больше работы, чем то, что злоумышленник может получить от нее.
Если у вас есть доступ к коду, включая возможность изменить его или создать измененную копию, все ставки в любом случае отключены.
Но основное внимание уделяется не такой безопасности, а тому, чтобы помочь разработчикам правильно использовать библиотеку. Перед модульной системой любыеpublic
класс и его public
или protected
члены были доступны и даже предлагались IDE, например, при завершении кода, автоматически, и потребовались дополнительные усилия, чтобы сообщить IDE, что определенные классы или члены не являются частью API и поэтому не должны предлагаться или даже отклоняться при компиляции кода, ссылающегося на них.
В настоящее время с модулем требуются дополнительные усилия, чтобы снова сделать доступными артефакты, не относящиеся к API, что значительно меняет игру. Теперь сделать артефакт, не относящийся к API, снова доступным, одинаково сложно, независимо от его модификаторов доступа, поэтому вы не можете ошибочно думать, что что-то является частью API только потому, что оноpublic
.
Точно так же вы не можете ожидать, что разработчик библиотеки будет поддерживать обратную совместимость с внутренними взломами Reflection. Полностью предотвратить такие обращения нельзя. Но чем больше усилий потребуется разработчику для создания такого кода, тем лучше он будет знать, что он сбился с пути и не может ожидать, что результат продолжит работать в следующей версии.