2012-07-03 3 views
4

У меня есть небольшой Java-апплет, и у меня есть раздражающая проблема. У меня есть подписан мой JAR с моим собственным хранилищем ключей с использованием инструмента jarsigner (после этих instructions).«java.security.AccessControlException: access denied», выполняющий подписанный Java-апплет

Java-апплет загружает подписанный JAR и пытается запустить его с расширенным классом URLClassLoader. Этот JAR пытается выполнить эту строку кода:

ClassLoader.getSystemClassLoader().getResource("aResource"); 

Он не может с большой трассировки стека завершившегося:

Caused by: java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "getClassLoader") 
    at java.security.AccessControlContext.checkPermission(AccessControlContext.java:366) 
    at java.security.AccessController.checkPermission(AccessController.java:555) 
    at java.lang.SecurityManager.checkPermission(SecurityManager.java:549) 
    at java.lang.ClassLoader.getSystemClassLoader(ClassLoader.java:1476) 
    at test.SecondJAR.main(SecondJAR.java:8) 

(линия 8 из test.SecondJAR соответствует getResource(...) метод

Когда запускается Java-апплет, пользователю предлагается принять сертификат, если он доверяет издателю:

Message to the user

Даже если я принимаю его, произошло исключение. Даже если я устанавливаю сертификат, и приглашение автоматически принимается, произошло исключение.

Я попытался тоже это:

AccessController.doPrivileged(new PrivilegedAction<Object>() { 
    public Object run() { 
     ClassLoader.getSystemClassLoader().getResource("aResource"); 
     return null; 
    } 
}); 

И он терпит неудачу с тем же исключением.

Любая помощь будет оценена!

+0

Вы, кажется, говорите, что исключение исходит из 'getSystemClassLoader' или' getResource', но трассировка стека говорит 'getContextClassLoader' (использование которого редко бывает хорошей идеей). Возможно, было бы полезно немного больше трассировки стека. –

+0

Таким образом, исключение вызывается загруженным кодом. По умолчанию «URLClassLoader» будет использовать разрешения (через «ProtectionDomain»), подходящие для того, откуда был загружен код (политика одинакового происхождения). Это очень трудно понять. Вам действительно нужно это делать? По всей видимости, общая причина, по которой можно попробовать такие вещи, - это не продолжать подписывать код. Мобильный код должен быть подписан, чтобы быть доверенным по уважительной причине! –

+0

@Tom У меня есть _Downloader Applet_, который получает сгенерированный JAR. этот JAR отличается каждый раз и отличается для каждого пользователя. Я должен загружать его каждый раз и выполнять его. второй JAR тоже подписан! должен существовать способ сделать это ;-( – logoff

ответ

8

Наконец-то я нашел ответ!

Я следил за рекомендациями Andrew Thomson, и я создал обычай SecurityManager. Мой маленький менеджер безопасности выглядит так:

private class MySecurityManager extends SecurityManager { 
    @Override 
    public void checkPermission(Permission perm) { 
     return; 
    } 
} 

Это забытый менеджер безопасности, который принимает все разрешения. Он должен быть улучшен, позволяя получать только систему ClassLoader во время выполнения.

Чтобы использовать свою уродливую SecurityManager я добавил эти строки в начале Java Applet start() метода:

SecurityManager sm = new MySecurityManager(); 
System.setSecurityManager(sm); 

С помощью этого обходного пути, весь процесс работал, как и ожидалось!

Возможно, существуют другие (лучшие) решения, но это сработало для меня.

Спасибо всем!

+1

Рад, что вы его отсортировали. :) Но я подозреваю, что Том (кто знает 100 раз больше о безопасности, чем я), рекомендовал бы более ограниченный менеджер безопасности, чем это. Из моих ограниченных знаний менеджер безопасности, который позволяет динамически загружать «все привилегии» кода (который, BTW является менее ограничительным SM, чем применяется к *** доверенному аплету ***), является «слишком большим» разрешением. –

+0

... как «например». Представьте, что запущенный код создает «JFrame», который вызывает 'setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE)' - казалось бы, невиновен, но он завершает работу JVM, который запускает фрейм, или, возможно, также ** апплет **. Типичный доверенный апплет Security Manager (SM) не разрешил бы вызывать 'System.exit (n)'. Этот апплет может работать на веб-странице, где несколько апплетов используют ** ту же ** JVM. Это «гость» в этой JVM, но он эффективно «сжигает гостевой дом», заканчивая JVM! –

+0

Я согласен на 100%, но в любом случае, как я уже упоминал, можно создать SecurityManager, разрешающий только определенные разрешения. Я понимаю недостатки добавления этих привилегий, но это единственный способ, которым я нашел. Я ожидаю, что кто-то еще покажет мне правильный, лучший и стандартный способ достижения моей цели: выполнить подписанные ресурсы, загруженные во время выполнения. – logoff

2

Проблема в том, что JRE рассматривает только код в исходном коде , которому следует доверять. Двумя возможными решениями являются:

  1. Установите персонализированный менеджер безопасности, который позволяет новому коду обладать необходимыми ему привилегиями.
  2. Оберните новый код в PrivilegedAction & назовите его от AccessController.doPrivileged(..) метод (только что пришло мне как возможность, не уверен, насколько я понимаю его объем, полностью непроверенный).
+0

Я отредактировал мой вопрос добавляет 'AccessController.doPrivileged (...)', но я понял, что он тоже не работает. Как установить настраиваемый менеджер безопасности? – logoff

+0

@logoff Настройка менеджера безопасности в апплете может установить его для других апплетов. –

+0

@Tom, второй JAR не является апплетом, но в любом случае, как я могу установить диспетчер безопасности, чтобы избежать этого исключения? – logoff

 Смежные вопросы

  • Нет связанных вопросов^_^