Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Коллоквиум 2012.doc
Скачиваний:
31
Добавлен:
25.08.2019
Размер:
346.11 Кб
Скачать

12. Модель безопасности Java. Policy, Permissions, AccessController

Модель безопасности Java реализована на настраиваемом "sandbox" - области, в которой апплет имеет возможность безопасно выполняться без возможности нанесения системе какого-либо ущерба. Апплет не может выйти за пределы «песочницы» ("sandbox" в переводе с английского означает «песочница»). Также «песочница» не дает исполнять апплетам следующие действия: - Читать или записывать файлы, также запрещены любые операции, связанные с файлами (проверка типа, временной метки, переименование). - Создание сетевых соединений к машинам, выходящим за пределы сети узла, на котором запущен апплет. - Вызов родного кода. - Печать. - Создание дополнительного окна, не содержащего предупреждающего сообщения (по умолчанию апплетам разрешено создавать только окна, содержащие информационные, предупреждающие сообщения и сообщения об ошибках, создание дочерних окон с элементами управления запрещено). Современные браузеры с поддержкой Java обязаны придерживаться этих ограничений.

Все апплеты в сети делятся на те, которым доверяют (trusted), и те, которым не доверяют (untrusted). Первым дается большая свобода действий. Чтобы апплет заслужил доверие, разработчик должен подписать его собственным электронным ключом. Сделать это нужно с помощью Java Development Kit (JDK).  Цифровая подпись Java основана на технологии шифрования с открытым ключом. Принцип шифрования открытым ключом предполагает, что информация, зашифрованная одной стороной, может быть расшифрована второй стороной известным только ей личным ключом, связанным с первым некой математической функцией. Благодаря технологии цифровых подписей, разработчик может применить свой личный ключ к фрагменту кода Java, а затем завизировать его у уполномоченного по выдаче сертификатов (Certificate Authority, CA). Последняя подпись удостоверяет личность держателя пары ключей. Принимающая сторона проверяет сертификат уполномоченного, а также то, что информация об отправителе кода не устарела и не была отозвана.

Как известно, в виртуальной машине класс определяется своим полным именем и экземпляром ClassLoader’а которым он был загружен. Так, для VM классы с абсолютно одинаковыми именами, загруженные разными ClassLoader’ами будут разными: к примеру, попытка привести один из объект такого класса к другому обречена на провал. В модели безопасности Java с любым классом кроме ClassLoader’а связана еще одна сущность: code base, место, откуда класс был загружен (URL ресурса или ссылка на локальный ресурс). Кроме того, у класса может быть сертификат. Code location и сертификаты (если есть) вместе образуют code source.

Permission – это класс, который идентифицирует доступность какого-нибудь действия. К примеру FilePermission – контролирует доступность операций над частью файловой системы. Рermission состоит из двух частей – имени и списка действий. Code Source и коллекция разрешений – образуют домен безопасности (protection domain). С каждым классом ассоциируется домен безопасности (не каждый класс, правда, сможет его посмотреть). Последний из ключевых классов модели – SecurityManager. Его задача – давать окончательный ответ на вопрос “а стоит ли разрешить действие”, которое пытается выполнить класс. Есть несколько нюансов, которые необходимо понимать при использовании SecurityManager’а. Самый основной: безопасность проверяется в некотором контексте. SecurityManager проверяет не просто доступность действия, он исследует все классы из текущего стека на предмет соответствия политике безопасности. Если хотя бы один из классов не имеет достаточных прав – будет выброшен SecurityException. SecurityManager, естественно, не занимается проверкой безопасности единолично. Для проверки всего контекста используется AccessController, который в свою очередь передает работу AccessControllerContext. AccessControllerContext инкапсулирует контекст вызова (стек) и именно он проводит окончательную проверку: Политика безопасности сопоставляет Code Source (что за код выполяется) Principal (кто выполняет код) c наборами разрешений. В Java политика реализуется при помощи классов наследников java.security.Policy (сам класс – абстрактный). В JDK есть только один наследник Policy: PolicyFile. Как и следует из названия PolicyFile в качестве источника информации о правах использует файл. Файл с описанием политики по умолчанию находится в JRE_HOME/lib/security/java.policy. В самом простом варианте, файл состоит из блоков grant, в которых описаны разрешения в формате permission <Класс Permission> “<имя Permission’a>”, “<значение>”.

13. Generics Java

Начиная с версии Java 5 в языке появился механизм обобщённого программирования — шаблоны, внешне близкие к шаблонам C++. С помощью специального синтаксиса в описании классов и методов можно указать параметры-типы, которые внутри описания могут использоваться в качестве типов полей, параметров и возвращаемых значений методов.

 Объявление обобщённого класса class GenericClass<E>  {   E getFirst() { ... }   void add(E obj) { ... } } Использование обобщённого класса в коде GenericClass <String> var = new GenericClass<String>(); var.add("qwerty"); String p = var.getFirst();

Generic позволяют объявлять классы, интерфейсы и методы, где тип данных и ограничения на него, которыми они оперируют указан в виде параметра Позволяют реализовать код, который будет работать единообразно с разными типами данных В отличие от использования ссылок на тип Object предоставляют безопасные с точки зрения типизации средства обобщенного программирования Спецификация параметра задается явно (классы, интерфейсы и ссылки) или выводится на основании аргументов (вызов методов) Соответствие типа проверяется на стадии компиляции

Отличия от С++: - При объявлении специфической ссылки имеющей типом родовой класс или интерфейс не происходит генерация кода класса (интерфейса) - Все объекты – специфические экземпляры родового класса разделяют один и тот же обобщенный тип - Параметрами родового компонента могут быть только типы - На параметры родового компонента можно наложить ограничения по наследованию определенного типа и/или интерфейса (интерфейсов) - Исключения и перечисления не могут быть родовыми типами - В качестве значений параметров при спецификации не могут использоваться примитивные типы java

Маски являются еще одним отличием Java generic-ов от шаблонов С++. Они используются тогда, когда нужно абстрагироваться от конкретных аргументов типа, и позволяют использовать его там, где не требуется знать конкретные типы параметров. Например, это может быть метод, который очищает список, или метод, которому не интересен тип ключа карты (Map), т.к. он оперирует только со значениями. Приведенные ниже примеры помогут более подробно разобраться, что такое маски и для чего они нужны. Синтаксически маска – это выражение, состоящее из символа ‘?’, и, возможно, ограничений, например, ‘? extends T’ или ‘? super T’, где T – тип. Чаще маски применяются при описании типов параметров методов, но их также можно использовать просто в объявлении переменных в теле метода или членов класса.

Возможность использовать параметр generic-класса или метода в throws позволяет при описании абстрактного метода не ограничивать разработчика, использующего класс или интерфейс, конкретным типом исключения. Но использовать тип, заданный в качестве параметра, в catch-выражениях нельзя. Кроме того, можно сгенерировать исключение, тип которого задается generic-параметром, но экземпляр должен быть создан извне. Это ограничение порождается одним из ограничений Java generic-ов - нельзя создать объект, используя оператор new, тип которого является параметром generic-а.  Нет доступа к информации о типе параметра (кроме той, что задается через ограничение extends) и на этапе компиляции, что делает невозможным использование этого типа вместе с оператором new. Reflection позволяет получить информацию о generic-параметрах, ограничениях и масках, но эта все та же информация, которая была доступна на этапе компиляции. Это означает, что будет доступно число параметров, типы, от которых параметры должны быть унаследованы и т.д., но информацию о том, каким типом параметризован конкретный экземпляр, получить невозможно.

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

Самая большая проблема вытекает из того, что в Java 1.5 компилятор не порождает отдельные специализации generic-класса для каждого применения, как это сделано в C++. С одной стороны, это позволило избежать проблем с совместимостью, т.к. не требует внесения изменений в формат байт-кода, но с другой стороны, повлекло за собой множество неприятных ограничений. В generic-классе или интерфейсе невозможно объявить статическую переменную, тип которой являлся бы параметром типа. Кроме того, статические методы не могут получить доступ к параметрам generic-класса, в котором они находятся, хотя сами могут быть параметризованы и могут использовать свои параметры. По той же причине нет специализаций generic-ов для конкретных типов параметров.  Ни generic-классы, ни generic-интерфейсы не могут быть унаследованными от типа, переданного в качестве параметра. Это невозможно из-за того, что существует только одна реализация generic-типа на все случаи его применения. Кроме того, это привело бы к неоднозначности: неизвестно, что передается в качестве параметра – класс или интерфейс. 

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]