Java - это объектно-ориентированная система программирования, поэтому и управление доступом в ней спроектировано и реализовано в объектном стиле. По этой причине рассмотреть Java-среду для нас очень важно.
Прежде всего, остановимся на эволюции модели безопасности Java. В JDK 1.0 была предложена концепция "песочницы" (sandbox) - замкнутой среды, в которой выполняются потенциально ненадежные программы (апплеты, поступившие по сети). Программы, располагающиеся на локальном компьютере, считались абсолютно надежными, и им было доступно все, что доступно виртуальной Java-машине.
В число ограничений, налагаемых "песочницей", входит запрет на доступ к локальной файловой системе, на сетевое взаимодействие со всеми хостами, кроме источника апплета, и т.п. Независимо от уровня достигаемой при этом безопасности (а проблемы возникали и с разделением свой/чужой, и с определением источника апплета), наложенные ограничения следует признать слишком обременительными: возможности для содержательных действий у апплетов почти не остается.
Чтобы справиться с этой проблемой, в JDK 1.1 ввели деление источников (точнее, распространителей) апплетов на надежные и ненадежные (источник определялся по электронной подписи). Надежные апплеты приравнивались в правах к "родному" коду. Сделанное послабление решило проблемы тех, кому прав не хватало, но защита осталась неэшелонированной и, следовательно, неполной.
В JDK 1.2 сформировалась модель безопасности, используемая и в Java 2. От модели "песочницы" отказались. Оформились три основных понятия:
источник программы;
право и множество прав;
политика безопасности.
Источник программы определяется парой (URL, распространители программы). Последние задаются набором цифровых сертификатов.
Право - это абстрактное понятие, за которым, как и положено в объектной среде, стоят классы и объекты. В большинстве случаев право определяется двумя цепочками символов - именем ресурса и действием. Например, в качестве ресурса может выступать файл, а в качестве действия - чтение. Важнейшим методом "правовых" объектов является implies(). Он проверяет, следует ли одно право (запрашиваемое) из другого (имеющегося).
Политика безопасности задает соответствие между источником и правами поступивших из него программ (формально можно считать, что каждому источнику соответствует своя "песочница"). В JDK 1.2 "родные" программы не имеют каких-либо привилегий в плане безопасности, и политика по отношению к ним может быть любой. В результате получился традиционный для современных ОС и СУБД механизм прав доступа со следующими особенностями:
Java-программы выступают не от имени пользователя, их запустившего, а от имени источника программы. (Это весьма глубокая и прогрессивная трактовка, если ее правильно развить, см. следующий раздел);
нет понятия владельца ресурсов, который мог бы менять права; последние задаются исключительно политикой безопасности (формально можно считать, что владельцем всего является тот, кто формирует политику);
механизмы безопасности снабжены объектной оберткой.
Весьма важным понятием в модели безопасности JDK 1.2 является контекст выполнения. Когда виртуальная Java-машина проверяет права доступа объекта к системному ресурсу, она рассматривает не только текущий объект, но и предыдущие элементы стека вызовов. Доступ предоставляется только тогда, когда нужным правом обладают все объекты в стеке. Разработчики Java называют это реализацией принципа минимизации привилегий.
На первый взгляд, учет контекста представляется логичным. Нельзя допускать, чтобы вызов какого-либо метода расширял права доступа хотя бы по той причине, что доступ к системным ресурсам осуществляется не напрямую, а с помощью системных объектов, имеющих все права.
К сожалению, подобные доводы противоречат одному из основных принципов объектного подхода - принципу инкапсуляции. Если объект A обращается к объекту B, он не может и не должен знать, как реализован B и какими ресурсами он пользуется для своих целей. Если A имеет право вызывать какой-либо метод B с некоторыми значениями аргументов, B обязан обслужить вызов. В противном случае при формировании политики безопасности придется учитывать возможный граф вызовов объектов, что, конечно же, нереально.
Разработчики Java осознавали эту проблему. Чтобы справиться с ней, они ввели понятие привилегированного интервала программы. При выполнении такого интервала контекст игнорируется. Привилегированная программа отвечает за себя, не интересуясь предысторией. Аналогом привилегированных программ являются файлы с битами переустановки идентификатора пользователя/группы в ОС Unix, что лишний раз подтверждает традиционность подхода, реализованного в JDK 1.2. Известны угрозы безопасности, которые привносят подобные файлы. Теперь это не лучшее средство ОС Unix перекочевало в Java.
Рассмотрим дисциплину контроля прав доступа более формально.
Класс AccessController (встроенный менеджер безопасности) предоставляет единый метод для проверки заданного права в текущем контексте - checkPermission (Permission). Это лучше (по причине параметризуемости), чем множество методов вида checkXXX, присутствующих в SecurityManager - динамически изменяемом менеджере безопасности из ранних версий JDK.
Пусть текущий контекст выполнения состоит из N стековых фреймов (верхний соответствует методу, вызвавшему checkPermission(p)). Метод checkPermission реализует следующий алгоритм (см. Листинг 10.1).
i = N;
while (i > 0) {
if (метод, породивший i-й фрейм, не имеет проверяемого
права) {
throw AccessControlException
} else if (i-й фрейм помечен как привилегированный) {
return;
}
i = i - 1;
};
// Выясним, есть ли проверяемое право у унаследованного контекста
inheritedContext.checkPermission (p);
Листинг 10.1. Алгоритм работы метода checkPermission класса AccessController. (html, txt)
Сначала в стеке ищется фрейм, не обладающий проверяемым правом. Проверка производится до тех пор, пока либо не будет исчерпан стек, либо не встретится "привилегированный" фрейм, созданный в результате обращения к методу doPrivileged(PrivilegedAction) класса AccessController. Если при порождении текущего потока выполнения был сохранен контекст inheritedContext, проверяется и он. При положительном результате проверки метод checkPermission(p) возвращает управление, при отрицательном возникает исключительная ситуация AccessControlException.
Выбранный подход имеет один недостаток - тяжеловесность реализации. В частности, при порождении нового потока управления с ним приходится ассоциировать зафиксированный "родительский" контекст и, соответственно, проверять последний в процессе контроля прав доступа.
Отметим, что этот подход не распространяется на распределенный случай (хотя бы потому, что контекст имеет лишь локальный смысл, как, впрочем, и политика безопасности).
В целом средства управления доступом в JDK 1.2 можно оценить как "наполовину объектные". Реализация оформлена в виде интерфейсов и классов, однако по-прежнему разграничивается доступ к необъектным сущностям - ресурсам в традиционном понимании. Не учитывается семантика доступа. Имеют место и другие отмеченные выше концептуальные проблемы.
Возможный подход к управлению доступом в распределенной объектной среде
Представляется, что в настоящее время проблема управления доступом существует в трех почти не связанных между собой проявлениях:
традиционные модели (дискреционная и мандатная);
модель "песочница" (предложенная для Java-среды и близкой ей системы Safe-Tcl);
модель фильтрации (используемая в межсетевых экранах).
На наш взгляд, необходимо объединить существующие подходы на основе их развития и обобщения.
Формальная постановка задачи разграничения доступа может выглядеть следующим образом.
Рассматривается множество объектов (в смысле объектно-ориентированного программирования). Часть объектов может являться контейнерами, группирующими объекты-компоненты, задающими для них общий контекст, выполняющими общие функции и реализующими перебор компонентов. Контейнеры либо вложены друг в друга, либо не имеют общих компонентов.
С каждым объектом ассоциирован набор интерфейсов, снабженных дескрипторами (ДИ). К объекту можно обратиться только посредством ДИ. Разные интерфейсы могут предоставлять разные методы и быть доступными для разных объектов.
Каждый контейнер позволяет опросить набор ДИ объектов-компонентов, удовлетворяющих некоторому условию. Возвращаемый результат в общем случае зависит от вызывающего объекта.
Объекты изолированы друг от друга. Единственным видом межобъектного взаимодействия является вызов метода.
Предполагается, что используются надежные средства аутентификации и защиты коммуникаций. В плане разграничения доступа локальные и удаленные вызовы не различаются.
Предполагается также, что разрешение или запрет на доступ не зависят от возможного параллельного выполнения методов (синхронизация представляет отдельную проблему, которая здесь не рассматривается).
Разграничивается доступ к интерфейсам объектов, а также к методам объектов (с учетом значений фактических параметров вызова). Правила разграничения доступа (ПРД) задаются в виде предикатов над объектами.
Рассматривается задача разграничения доступа для выделенного контейнера CC, компонентами которого должны являться вызывающий и/или вызываемый объекты. ДИ этого контейнера полагается общеизвестным. Считается также, что между внешними по отношению к выделенному контейнеру объектами возможны любые вызовы.
Выполнение ПРД контролируется монитором обращений.
При вызове метода мы будем разделять действия, производимые вызывающим объектом (инициация вызова) и вызываемым методом (прием и завершение вызова).
При инициации вызова может производиться преобразование ДИ фактических параметров к виду, доступному вызываемому методу ("трансляция интерфейса"). Трансляция может иметь место, если вызываемый объект не входит в тот же контейнер, что и вызывающий.
Параметры методов могут быть входными и/или выходными. При приеме вызова возникает информационный поток из входных параметров в вызываемый объект. В момент завершения вызова возникает информационный поток из вызываемого объекта в выходные параметры. Эти потоки могут фигурировать в правилах разграничения доступа.
Структурируем множество всех ПРД, выделив четыре группы правил:
политика безопасности контейнера;
ограничения на вызываемый метод;
ограничения на вызывающий метод;
добровольно налагаемые ограничения.
Правила, общие для всех объектов, входящих в контейнер C, назовем политикой безопасности данного контейнера.
Пусть метод M1 объекта O1 в точке P1 своего выполнения должен вызвать метод M объекта O. Правила, которым должен удовлетворять M, можно разделить на четыре следующие подгруппы:
правила, описывающие требования к формальным параметрам вызова;
правила, описывающие требования к семантике M;
реализационные правила, накладывающие ограничения на возможные реализации M;
правила, накладывающие ограничения на вызываемый объект O.
Метод M объекта O, потенциально доступный для вызова, может предъявлять к вызывающему объекту следующие группы требований:
правила, описывающие требования к фактическим параметрам вызова;
правила, накладывающие ограничения на вызывающий объект.
Можно выделить три разновидности предикатов, соответствующих семантике и/или особенностям реализации методов:
утверждения о фактических параметрах вызова метода M в точке P1;
предикат, описывающий семантику метода M;
предикат, описывающий особенности реализации метода M.
Перечисленные ограничения можно назвать добровольными, поскольку они соответствуют реальному поведению объектов и не связаны с какими-либо внешними требованиями.
Предложенная постановка задачи разграничения доступа соответствует современному этапу развития программирования, она позволяет выразить сколь угодно сложную политику безопасности, найти баланс между богатством выразительных возможностей и эффективностью работы монитора обращений.
ЗАКЛЮЧЕНИЕ
Идентификация - процедура распознавания субъекта по его уникальному идентификатору, присвоенному данному субъекту ранее и занесенному в базу данных в момент регистрации субъекта в качестве легального пользователя системы.
Аутентификация - процедура проверки подлинности входящего в систему объекта, предъявившего свой идентификатор. В зависимости от степени доверительных отношений, структуры, особенностей сети и удаленностью объекта проверка может быть односторонней или взаимной. В большинстве случаев она состоит в процедуре обмена между входящим в систему объектом и ресурсом, отвечающим за принятие решения ("да" или "нет"). Данная проверка, как правило, производится с применением криптографических преобразований, которые нужны, с одной стороны, для того, чтобы достоверно убедиться в том, что субъект является тем, за кого себя выдает, с другой стороны - для защиты трафика обмена субъект система от злоумышленника. Таким образом, идентификация и аутентификация являются взаимосвязанными процессами распознавания и проверки подлинности пользователей.
Именно от корректности решения этих двух задач (распознавания и проверки подлинности) зависит, можно ли разрешить доступ к ресурсам системы конкретному пользователю, т.е. будет ли он авторизован.
Список использованной литературы
1. http://www.studentline.ru/
2. http://www.sernam.ru/
3. http://www.citforum.ru/
4. http://www.mywereee.ru
5. https://ru.wikipedia.org/wiki/