Предоставляет ли AccessController.doPrivileged права на JavaScript для разрешений подписанного апплета?

Я смотрю на подписанный апплет, который сильно вызван из JavaScript. Очевидно, что потоки, созданные из JavaScript, более изолированы, чем любой поток, запущенный непосредственно из Java. Например, если поток JavaScript вызывает в Applet и регистрирует что-то, что заставляет файл журнала катиться, генерируется исключение безопасности. Любой поток, запущенный непосредственно внутри апплета, не будет испытывать это исключение безопасности. Решение здесь с log4j заключается в использовании асинхронного приложения.

Но с другими исключениями безопасности (например, с использованием Apache Axis в подписанном апплете, но в потоке JavaScript) нет очевидного способа иметь некоторый асинхронный поток. Скажем, у меня есть следующий код, который, если вызывается из потока Java, будет работать, и если вызов через JavaScript завершится с безопасностьюException:

public void someMethodCalledFromJavaScript() {
  // Stuff that would throw a SecurityException
}

Я вижу три следующих параметра, но они могут быть недействительными. Ради этого обсуждения проигнорируйте, будет ли выполнение синхронным или асинхронным, так как это легко управляется. Мне сложно понять детали модели безопасности. Вот мои три возможных варианта:

  • Начать новую тему (будет ли это работать даже?):

    public void someMethodCalledFromJavaScript() {
      new Thread(new Runnable() {
        public void run() {
          // Stuff that would throw a SecurityException
        }
      }).start();
    }
    
  • У Applet есть поток, готовый идти все время, запускаемый через поток исходного кода JavaScript (здесь очень упрощенный код):

    private volatile boolean doit = false;
    
    // This code is running in a Thread, started @ Applet init time
    public void alwaysWaiting() {
      while (true) {
        if (doit) {
          doit = false;
          // Stuff that would throw a SecurityException
        }
      }
    }
    
    public void someMethodCalledFromJavaScript() {
      doit = true;
    }
    
  • Использовать AccessController.doPrivileged:

    public void someMethodCalledFromJavaScript() {
      AccessController.doPrivileged(new PrivilegedAction() {
        public Object run() {
          // Stuff that would throw a SecurityException
          return null;
        }
      });
    }
    

В соответствии с тем, что я читал в AccessController.doPrivileged, вы запускаете с пересечением существующих привилегий безопасности и привилегий домена безопасности кода, который вы вызываете. Для меня это не имеет смысла, как если бы вы работали с пересечением низкого и высокого домена безопасности, у вас будет только домен с низкой степенью защиты. Так что я не понимаю что-то.

Конкретный SecurityException, который я вижу, следующий:

java.security.AccessControlException: access denied (java.lang.RuntimePermission accessDeclaredMembers)

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

Какие варианты выше будут работать, и которые лучше других, и почему.

Ответ 1

  • "Начать новую тему (будет ли это работать даже?)"

Не работает по причинам, указанным ниже

  • У Applet есть поток, готовый идти в любое время, запускаемый через поток исходного кода JavaScript

Будет работать, конечно, но более болезненным, чем вызов doPrivileged, но имеет тот же эффект семантически.

  • Использовать AccessController.doPrivileged

Да, это сработает.

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

Если проверяемая привилегия не находится в каждом отдельном фрейме в этом наборе, проверка не выполняется.

Другими словами, текущие привилегии потока - это пересечение привилегий в этом наборе.

Так, например, если привилегированный код doPrivileged некоторый непривилегированный код, который пытается открыть файл, проверка завершится неудачно. Аналогично, если непривилегированный код doPrivileged привилегированный код, который открывает файл, проверка завершится неудачно. Но если непривилегированный код вызывает привилегированный код, а привилегированный код в свою очередь вызывает doPrivileged, чтобы открыть файл, проверка будет успешной.

В теории вы должны иметь возможность предоставить только вашу Java-кодовую базу привилегий (возможно, доступ к какой-либо изолированной директории), а затем предоставить те же привилегии для кода JavaScript, который будет использовать этот привилегированный код, но я сомневаюсь, что браузер имеет такие функции. Я удивлен, что JavaScript даже работает в другом домене защиты, чем Java.

Я никогда не выполнял JavaScript ↔ Java interop, но, похоже, что вам не придется делать методы, которые вызывают JavaScript, используют блоки doPrivileged для всего тела.


EDIT: Как сказал Сами, будьте осторожны при вызове блоков doPrivileged в привилегированном коде (и прочитайте его ответ).

Ответ 2

Я бы пошел с doPrivileged. Просто имейте в виду, что все, у кого есть доступ к вашему апплету, могут загрузить его и разместить на своем сайте, а их собственный вредоносный javascript называть его так, как вы этого не себе представляли.

Последствия для безопасности других решений практически одинаковы (EDIT: хотя создание нового потока не работает, как указал Longpoke), но они сложнее. Поэтому я не вижу в них никакого преимущества.

AccessController.doPrivileged рассматривает домен защиты только непосредственно вызывающего. В вашем примере класс, в котором определен ваш метод someMethodCalledFromJavaScript. Если это доверенный класс в подписанной банке, не имеет значения, что ненадежный Javascript вызывает его.