SecurityManager не разрешает чтение файла, хотя это указано в политике

Это моя ошибка:

java.security.AccessControlException: access denied ("java.io.FilePermission" "C:\Temp\SettingsApp.policy" "read")

Это моя политика (динамически создается для каждого приложения)

grant signedBy "SmartMirror" {
    permission java.lang.RuntimePermission "setSecurityManager";
    permission java.lang.RuntimePermission "getSecurityManager";
    permission java.lang.RuntimePermission "createSecurityManager";
    permission java.lang.RuntimePermission "usePolicy";
};

grant signedBy "currentUser" codeBase "file:/C:/Temp/SettingsApp.jar" {
    permission java.io.FilePermission "C:/Temp/SettingsApp.policy", "read";
};

Вот как я устанавливаю политику и использую диспетчер безопасности:

System.setSecurityManager(null); // reset so can reload new policy
System.setProperty("java.security.policy", "file:/C:/Temp/" + app.getName() + ".policy");
System.setSecurityManager(new SecurityManager()); // instance with new policy
JPanel panel = (JPanel) app.getObject().newInstance(); // instance Class <?>

Файл jar загружается вот так и отлично работает:

try {
    appLoader = URLClassLoader.newInstance(new URL[] { download }); // download is a URL of the C:/Temp/SettingsApp.jar
    appBuilder = appLoader.loadClass("iezon.app." + name); // name is SettingsApp
} catch (ClassNotFoundException e) {
    // TODO: Add class not found error for Application (App Developer issue)
}

Когда JPanel panel = (JPanel) app.getObject().newInstance(); запускается в первый раз, он работает нормально и возвращается JPanel. Однако, если я попытаюсь запустить его во второй раз, я получаю сообщение об ошибке.

Вот где я получаю сообщение об ошибке:

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

Что затем приводит к чтению файла, потому что по умолчанию этот файл содержит построчную политику, которую он хочет запросить, которая затем переписывается в настоящую политику:

public ArrayList<String> readPolicy(App app) {

    String line = null;
    try {
        ArrayList<String> builder = new ArrayList<String>();
        FileReader fileReader = new FileReader("C:/Temp/" + app.getName() + ".policy");
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        while ((line = bufferedReader.readLine()) != null) {
            builder.add(line);
        }
        bufferedReader.close(); 
        return builder;
    } catch (IOException ex) {
        ex.printStackTrace();
        return new ArrayList<String>();
    }
}

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 signedBy \"SmartMirror\" {");
        bufferedWriter.newLine();
        bufferedWriter.write("    permission java.lang.RuntimePermission \"setSecurityManager\";");
        bufferedWriter.newLine();
        bufferedWriter.write("    permission java.lang.RuntimePermission \"getSecurityManager\";");
        bufferedWriter.newLine();
        bufferedWriter.write("    permission java.lang.RuntimePermission \"createSecurityManager\";");
        bufferedWriter.newLine();
        bufferedWriter.write("    permission java.lang.RuntimePermission \"usePolicy\";");
        bufferedWriter.newLine();
        bufferedWriter.write("};");

        bufferedWriter.newLine();
        bufferedWriter.newLine();
        bufferedWriter.write("grant signedBy \"" + Init.usrController.getCurrentUser().getFname() + Init.usrController.getCurrentUser().getLname() + "\" codeBase \"file:/C:/Temp/" + app.getName() + ".jar\" {");
        bufferedWriter.newLine();

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


        bufferedWriter.write("    permission java.io.FilePermission \"C:/Temp/" + app.getName() + ".policy\", \"read\";");
        bufferedWriter.newLine();

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

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

Проблемный код не вызывается между операторами System.setSecurityManager(null); и System.setSecurityManager(new SecurityManager());, поэтому при второй попытке он отклоняется ранее установленным менеджером безопасности, который все еще установлен на этом этапе. Но, как сказано в других вопросах и ответах, вы никогда не должны устанавливать диспетчер безопасности на null, даже на долю секунды. Вы должны предоставить своему коду все необходимые права для выполнения изменения.

Holger 20.09.2018 14:58

@Holger Когда экземпляр Security Manager создается через System.setSecurityManager(new SecurityManager());, он не перезагружает никакие более поздние методы setProperty() с новыми политиками, нужно ли мне перезапускать java-файл с новой политикой?

Jaquarh 21.09.2018 20:08

Я не ожидал, что он что-нибудь перезагрузит. Таким образом, вы все равно можете вызвать в System.setSecurityManager(new SecurityManager()); для обновления, но без вызова System.setSecurityManager(null); перед этим.

Holger 22.09.2018 11:30
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
3
475
0

Другие вопросы по теме