Использование менеджера безопасности с отражением при доступе к файлу jar

После реализации моей платформы, позволяющей динамически загружать jar-файлы с помощью рефлексии, я столкнулся с проблемой безопасности. Файл jar может быть "опасным" и содержать код, который может на что-то повлиять, поэтому я сталкиваюсь на SO с использованием SecurityManager,

Я загружаю файл jar следующим образом (пример файла с жестким кодом):

URLClassLoader clsLoader = URLClassLoader
    .newInstance(new URL[] { new URL("file:/C://Temp/SettingsApp.jar") });
Class<?> cls = clsLoader.loadClass("iezon.app.SettingsApp");
JPanel settingsApp = (JPanel) cls.newInstance();

Я пытался использовать SecurityManager вот так:

try {
    SecurityManager sm = new SecurityManager();
    Object context = sm.getSecurityContext();
    sm.checkPermission(new AllPermission(), context);
    settingsAppPanel = (JPanel) cls.newInstance();
} catch (AccessControlException e) {
    e.printStackTrace();
}

Тест с AllPermission() работает и дает мне это исключение:

java.security.AccessControlException: доступ запрещен ("java.security.AllPermission" "" "")

Однако я не могу найти какую-либо информацию о том, как связать файл jar с этим менеджером безопасности, а не с текущей платформой. Я просто не хочу, чтобы файл jar мог открывать сокеты и т. Д. Без предварительного запроса разрешений, которые затем может принять пользователь.

Я наткнулся через BasicPermission однако это абстрактный класс, и его нельзя создавать как AllPermission и также я не могу найти какую-либо информацию о приближении к этому. Любая помощь будет оценена!

1 ответ

Как Holger в комментариях, единственный способ реализовать использование диспетчера безопасности - это динамически создавать политики. Поэтому, когда разработчик загружает новое приложение в магазин приложений, ему предоставляется набор политик для объявления того, что его приложение использует. В приложении это передается пользователю, который просит его подтвердить эту политику (на свой страх и риск, если он включает сокеты и т. Д.), А затем создается политика, и приложение может работать:

if (!app.policyIsAgreedTo()) {
        if(readPolicy(app).get(0).equalsIgnoreCase("grant {")) {
            app.setPolicy(true);
        } else {
            throw new Exception("App policy has not been agreed to.");
        }
    }

    if (app.policyIsAgreedTo()) {
        System.setProperty("java.security.policy", "file:/C:/Temp/" + app.getName() + ".policy");
        System.setSecurityManager(new SecurityManager());
        JPanel panel = (JPanel) app.getObject().newInstance();
        System.setSecurityManager(null);
        return panel;
    }

    throw new Exception("App policy has not been agreed to.");

Политика создается так:

public static void createPolicy(ArrayList<String> policies, App app) {

    try {
        FileWriter fileWriter =
                new FileWriter("C:/Temp/" + app.getName() + ".policy");
        BufferedWriter bufferedWriter =
                new BufferedWriter(fileWriter);

        bufferedWriter.write("grant {");
        bufferedWriter.newLine();

        for(String policy : policies) {
            bufferedWriter.write("    permission java.lang.RuntimePermission \"" + policy + "\";");
            bufferedWriter.newLine();
        }

        bufferedWriter.write("};");
        bufferedWriter.close();

    } catch(IOException ex) {
        ex.printStackTrace();
    }
}

Приложение выполняет API-вызов в магазине приложений, собирая разрешения, необходимые приложению, а затем просто createPolicy() вызывается с разрешениями в ArrayList, т.е.

new ArrayList<String>() {{ add("setSecurityManager"); }}; // Etc...
Другие вопросы по тегам