Управління доступом в Java-середовищі

Java - це об'єктно-орієнтована система програмування, тому й управління доступом в ній спроектовано і реалізовано в об'єктному стилі. З цієї причини розглянути Java-середовище для нас дуже важливо. Докладно про Java-технології та безпеки Java-середовища розказано в статті А. Таранова і В. Цішевського "Java на три роки" (Jet Info, 1998, 11-12). З дозволу авторів далі використовуються її фрагменти.

Перш за все, зупинимося на еволюції моделі безпеки 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 можна оцінити як "наполовину об'єктні". Реалізація оформлена у вигляді інтерфейсів і класів, проте як і раніше розмежовується доступ до необ'єктний сутностей - ресурсами в традиційному розумінні. Не враховується семантика доступу. Мають місце й інші зазначені вище концептуальні проблеми.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: