Java SecurityManager несколько потоков

#java #multithreading #security #securitymanager

#java #многопоточность #Безопасность #securitymanager

Вопрос:

Я пытался использовать пользовательский SecurityManager для изолирования некоторого загруженного извне кода. SecurityManager, который у меня есть, работает нормально. Я использовал тот же подход, что и в многочисленных сообщениях здесь: устанавливайте пользовательский менеджер всякий раз, когда выполняется потенциально опасный код, затем возвращайтесь к стандартному менеджеру. Это отлично работает и делает то, что я хочу. Однако приложение является многопоточным: 2 потока используют пользовательский менеджер, один использует менеджер по умолчанию. Это приводит к ситуации, когда правильная работа доверенного кода может быть заблокирована, поскольку другой поток просто установил пользовательский менеджер безопасности. Есть ли способ обойти это? В качестве альтернативы, есть ли вообще лучший способ? Я видел несколько сообщений, в которых говорилось об использовании разных политик с одним и тем же менеджером безопасности, но я не смог найти хороший пример этого. Любая помощь приветствуется.

Комментарии:

1. В каком направлении это делается? Это загруженный извне код, который требует (и которому предоставляются) более высокие разрешения?

2. Загружаемый извне код должен иметь минимальные разрешения, основной код / main thread (который загружает внешний код) должен иметь все разрешения.

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

4. Хорошо, мое предложение должно было быть в духе приведенного ниже предложения Питера.

5. Я использовал тот же подход, что и в многочисленных публикациях здесь: устанавливайте пользовательский менеджер всякий раз, когда выполняется потенциально опасный код, затем возвращайтесь к стандартному менеджеру. Тьфу, кто посоветовал это сделать? Вы всегда можете определить вызывающий поток и вызывающий AccessControlContext … так этого делать не следует (в двух словах, установка / отключение SM — это не правильный путь)

Ответ №1:

Ваш SecurityManager может проверить, какой поток запущен. Простой локальный поток сделает это, однако вам может понадобиться InheritableThreadLocal, чтобы любые дополнительные созданные потоки «наследовали» уровень безопасности потоков.

Комментарии:

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

2. спасибо за ответ. Теперь я реализовал нечто подобное: основной поток «регистрирует» те потоки, которые считаются ненадежными (используя их идентификаторы), а метод checkPermission в SecurityManger проверяет идентификатор вызывающего потока. Однако это, вероятно, не сработает в случае, если ненадежный код создает подпотоки. На данный момент это было бы запрещено. Но если бы это потребовалось, то описанный выше метод, скорее всего, дал бы сбой.

3. @coderino — я не знаю, как долго вы поддерживаете идентификаторы потоков, но имейте в виду, что нет гарантии, что идентификатор потока уникален в течение всего срока службы jvm (как указано в javadoc download.oracle.com/javase/6/docs/api/java/lang /… ).

4. Использование InheritableThreadLocal решает проблему вложенных потоков и неуникальных имен потоков. Вы можете вызвать весь свой поток «main» и изменить его с помощью Thread.setName().

5. @Peter Lawrey — ITL будет работать для потоков, созданных напрямую, до тех пор, пока значение является неизменяемым объектом (так что изменение значения родительского потока не изменяет значение дочернего). это не решает проблему общего потока (например, пулов потоков). в конечном счете, я все еще думаю, что предпочтительнее использовать архитектуру безопасности Java в том виде, в каком она была разработана, гораздо меньше риска «случайной» утечки привилегий. (кроме того, проблема уникальности касается идентификаторов потоков, а не имен).

Ответ №2:

Вы используете один securitymanager для всего вашего приложения. платформа безопасности Java была разработана для обработки этого сценария. способ заставить вещи работать — это использовать функцию codebases файла политики, которая позволяет назначать разные разрешения разным кодовым базам. вы можете назначить вашей «основной» кодовой базе «все разрешения», и она будет функционировать в обычном режиме. вы можете назначить любой импортированный код ограниченной кодовой базе.

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

Комментарии:

1. Я попробую это сделать. Есть ли какая-либо хорошая документация по этому вопросу, включая примеры?

2. добавлены ссылки на соответствующую документацию sun / oracle.

3. Отлично, спасибо. Я пройдусь по этим ссылкам, чтобы посмотреть, что я могу использовать.

Ответ №3:

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