Spec-Zone .ru
спецификации, руководства, описания, API
Содержание документации

API для Привилегированных Блоков


Краткий обзор

Этот документ обеспечивает вводную информацию о том, что "привилегированный" код и для чего это используется, сопровождается иллюстрациями использования API с особым вниманием к проблемам:

Фон: Что Это Означает "Дать Коду полномочия

Политика для установки SDK определяет, какие полномочия - какие типы доступов системного ресурса - позволяются для кода из указанных источников кода. "Источник кода" (типа CodeSource) по существу состоит из участка кода (URL) и ссылка на сертификат (ы), содержащий открытый ключ (и), соответствующий закрытому ключу (ам), используемому, чтобы подписать код (если это было подписано).

Политика представляется объектом Политики. Более определенно это представляется a Policy подкласс, обеспечивающий реализацию абстрактных методов в Policy class (который находится в java.security пакет).

Исходное расположение для информации о политике, используемой объектом Политики, до реализации Политики. Ссылочная реализация Политики получает свою информацию из конфигурационных файлов политики. См. Синтаксис Файла Реализации и Политики Политики Значения по умолчанию для информации о ссылочной реализации Политики и синтаксис, который должен использоваться в файлах политики, которые это читает. Для получения информации об использовании Средства осуществления политики, чтобы создать файл политики (не будучи должен знать необходимый синтаксис), см. документацию Средства осуществления политики (для Соляриса) (для Windows).

"Домен защиты" охватывает CodeSource и полномочия, предоставленные кодировать от что CodeSource, как определено политикой безопасности в настоящий момент в действительности. Таким образом классы, подписанные теми же самыми ключами и от того же самого URL, помещаются в тот же самый домен, и class принадлежит одному и только одному домену защиты. Классы, которые имеют те же самые полномочия, но являются из различных источников кода, принадлежат различным доменам.

Сегодня весь код, поставленный как часть SDK, считают системным кодом и выполняется в уникальном системном домене. У системного кода автоматически есть все полномочия.

Каждый апплет или приложение работают в его соответствующем домене, определенном его источником кода. Для апплета (или приложение, работающее под менеджером безопасности), чтобы быть позволенными выполнить защищенное действие (такое как чтение или запись файла), апплету или приложению нужно предоставить разрешение для того определенного действия.

Более определенно, всякий раз, когда доступ ресурса предпринимается, у всего кода, пересеченного потоком выполнения до той точки, должно быть разрешение для того доступа ресурса, если некоторый код потока не был отмечен как "привилегированный". Таким образом, предположите, что проверка управления доступом происходит в потоке выполнения, у которого есть цепочка многократных вызывающих сторон. (Думайте об этом как о многократных вызовах метода, которые потенциально пересекают границы домена защиты.), Когда AccessController checkPermission метод вызывается новой вызывающей стороной, основным алгоритмом для того, чтобы решить, позволить ли или отрицать, что запрошенный доступ следующие:

Если у кода для какой-либо вызывающей стороны в цепочке вызовов нет требуемого разрешения, AccessControlException бросается, если следующее не является истиной - вызывающая сторона, код которой предоставляют, упомянутое разрешение было отмечено как "привилегированный" (см. ниже), и все стороны, впоследствии вызванные этой вызывающей стороной (прямо или косвенно), у всех есть упомянутое разрешение.

Отмечание кода как "привилегированный" позволяет части доверяемого кода временно включить доступу к большему количеству ресурсов, чем доступны непосредственно коду, который вызывал это. Это необходимо в некоторых ситуациях. Например, приложению нельзя позволить прямой доступ к файлам, которые содержат шрифты, но системная утилита, чтобы вывести на экран документ должна получить те шрифты, от имени пользователя. Чтобы сделать это, системная утилита становится привилегированной, получая шрифты.

Используя doPrivileged API

Использование "привилегированной" функции описывается в следующих разделах.

Никакое возвращаемое значение, никакое выданное исключение

Если Вы не должны возвратить значение изнутри "привилегированного" блока, Вашего звонка doPrivileged может быть похожим на следующее:

   somemethod() {
        ...normal code here...
        AccessController.doPrivileged(new PrivilegedAction() {
            public Object run() {
                // privileged code goes here, for example:
                System.loadLibrary("awt");
                return null; // nothing to return
            }
        });
       ...normal code here...
  }
 

AccessController.doPrivileged метод берет объект типа java.security.PrivilegedAction и вызывает run метод в привилегированном режиме. Реализация гарантирует, что полномочия будут отменяться после run метод выполняется, даже если выполнение doPrivileged прерывается асинхронным исключением.

PrivilegedAction интерфейс с единственным методом, названным run, это возвращает Объект. Вышеупомянутый пример показывает создание реализации того интерфейса, используя анонимный внутренний class; конкретная реализация run метод предоставляется. Когда звонок doPrivileged делается, экземпляр реализации PrivilegedAction передают к этому. doPrivileged вызовы метода run метод от реализации PrivilegedAction после включения полномочиям, и возвратам run возвращаемое значение метода как doPrivileged возвращаемое значение (который игнорируется в этом примере).

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

Можно также вызвать doPrivileged не используя анонимный внутренний class, как в:

    somemethod() {
        ...normal code here...
        MyAction mya = new MyAction();
        // become privileged:
        AccessController.doPrivileged(mya);
       ...normal code here...
    }

    class MyAction implements PrivilegedAction {
        public MyAction() {};
        public Object run() {
            // privileged code goes here, for example:
            System.loadLibrary("awt");
            return null; // nothing to return
        }
    }

Будьте очень осторожны в своем использовании "привилегированной" конструкции, и всегда не забывайте делать привилегированный раздел кода как можно меньше, то есть, попытайтесь ограничить код в пределах run метод к только коду, который должен быть выполнен с полномочиями, и сделать более общие вещи вне run метод. Также отметьте что звонок doPrivileged должен быть сделан в коде, который хочет включить его полномочиям. Не испытывайте желание записать утилиту class, которая непосредственно вызывает doPrivileged поскольку это могло привести к дырам в системе безопасности. Можно записать служебные классы для PrivilegedAction классы, хотя, как показано в примере выше.

Возврат значений

Если Вы должны возвратить значение, можно сделать что-то как следующее:

   somemethod() {
        ...normal code here...
        String user = (String) AccessController.doPrivileged(
          new PrivilegedAction() {
            public Object run() {
                return System.getProperty("user.name");
            }
          }
        );
        ...normal code here...
  }
 

Отметьте, что это использование требует динамического броска на значении, возвращенном doPrivileged. Альтернатива должна использовать a final локальная переменная:

   somemethod() {
        ...normal code here...
        final String user[] = {null};
        AccessController.doPrivileged(
          new PrivilegedAction() {
            public Object run() {
                user[0] = System.getProperty("user.name");
                return null; // still need this
            }
          }
        );
        ...normal code here...
  }
 
Еще одна альтернатива должна была бы записать неанонимный class, который безопасно обрабатывает типы для Вас:
   somemethod() {
        ...normal code here...
        GetPropertyAction gpa = new GetPropertyAction("user.name");
        AccessController.doPrivileged(gpa);
        String user = gpa.getValue();
        ...normal code here...
   }

   class GetPropertyAction implements PrivilegedAction {
      private String property;
      private String value;
      public GetPropertyAction(String prop) { property = prop;}
      public Object run() { 
               value = System.getProperty(property);
               return value;
      } 
      public String getValue() {return value;}

   }

Примечание там не является теперь никакими включенными преобразованиями типа, хотя run метод все еще возвращает значение, таким образом, у Вас могла все еще быть "острота", если бы Вы хотели к:

   somemethod() {
        ...normal code here...
        String user = (String) AccessController.doPrivileged(
                                   new GetPropertyAction("user.name"));
        ...normal code here...
   }

Доступ к локальным переменным

Если Вы используете анонимный внутренний class, любые локальные переменные, к которым Вы получаете доступ, должны быть final. Например:

   somemethod() {
        ...normal code here...
        final String lib = "awt";
        AccessController.doPrivileged(new PrivilegedAction() {
            public Object run() {
                // privileged code goes here, for example:
                System.loadLibrary(lib);
                return null; // nothing to return
            }
        });
       ...normal code here...
  }
 

Переменная lib должен быть объявлен final если Вы намереваетесь использовать это в пределах привилегированного блока. См. "Внутренние Классы" спецификация для получения дополнительной информации об этой теме.

Если есть случаи, где невозможно сделать существующую переменную final (потому что это устанавливается многократно), тогда можно создать новое final переменная прямо перед вызовом doPrivileged, и набор, что переменная, равная другой переменной. Например:

   somemethod() {
        ...normal code here...
        String lib;
        ...
        // lib gets set multiple times so we can't make it final
        ...
        // create a final String that we can use inside of the run method
        final String fLib = lib;
        AccessController.doPrivileged(new PrivilegedAction() {
            public Object run() {
                // privileged code goes here, for example:
                System.loadLibrary(fLib);
                return null; // nothing to return
            }
        });
       ...normal code here...
  }
 

Обработка Исключений

Если действие, выполняемое в Вашем run метод мог выдать "проверенное" исключение (тот, который должен быть перечислен в throws пункт метода), тогда Вы должны использовать PrivilegedExceptionAction интерфейс вместо PrivilegedAction интерфейс:

   somemethod() throws FileNotFoundException {
        ...normal code here...
      try {
        FileInputStream fis = (FileInputStream) AccessController.doPrivileged(
          new PrivilegedExceptionAction() {
            public Object run() throws FileNotFoundException {
                return new FileInputStream("someFile");
            }
          }
        );
      } catch (PrivilegedActionException e) {
        // e.getException() should be an instance of FileNotFoundException,
        // as only "checked" exceptions will be "wrapped" in a
        // PrivilegedActionException.
        throw (FileNotFoundException) e.getException();
      }
        ...normal code here...
  }
 

Если проверенное исключение выдается во время выполнения run метод, это помещается в исключение "обертки" PrivilegedActionException, которое тогда выдается и должно быть поймано Вашим кодом, как иллюстрировано в вышеупомянутом примере..

Отражение

Одна тонкость, которую нужно рассмотреть, является взаимодействием этого API с отражением. doPrivileged() метод может быть вызван, отражающим образом используя java.lang.reflect.Method.invoke(). В этом случае полномочия, предоставленные в привилегированном режиме, не являются таковыми Method.invoke() но неотражающего кода, который вызвал это. Иначе, системные полномочия могли ошибочно (или злонамеренно) быть присужденными пользовательскому коду. Отметьте, что подобные требования существуют при использовании существующего API через отражение.

Oracle и/или его филиалы Авторское право © 1993, 2012, Oracle и/или его филиалы. Все права защищены.
Свяжитесь с Нами