Разрешено отклонение разрешения при извлечении системного свойства "os.arch", когда java Security Manager включен - PullRequest
0 голосов
/ 24 февраля 2020

У меня есть простое java приложение ClientApp, в котором Java Security Manager включен. Это приложение пытается вызвать метод Test jar, который выбирает системное свойство "os.arch". Поскольку это отнимает много времени, мы вызываем новый поток, используя задачу Completable.

Это дает исключение

java.util.concurrent.ExecutionException: java.security.AccessControlException: access denied ("java.util.PropertyPermission" "os.arch" "read")
    at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
    at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895)
    at SecurityApplication.ClientApp.main(ClientApp.java:23)
Caused by: java.security.AccessControlException: access denied ("java.util.PropertyPermission" "os.arch" "read")
    at java.security.AccessControlContext.checkPermission(AccessControlContext.java:472)
    at java.security.AccessController.checkPermission(AccessController.java:884)
    at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
    at java.lang.SecurityManager.checkPropertyAccess(SecurityManager.java:1294)
    at java.lang.System.getProperty(System.java:717)
    at com.ravindra.CustomSupplier.get(CustomSupplier.java:10)
    at com.ravindra.CustomSupplier.get(CustomSupplier.java:5)
    at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1590)
    at java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1582)
    at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
    at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
    at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
    at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)

ClientApp:

import com.test.App;

public class ClientApp
{
    public static void main(String[] args)
    {
        //Enable security 
        SecurityManager securityManager = new SecurityManager();
        System.setSecurityManager(securityManager);

        TestApp app = new TestApp();

        Future<String> future = app.getOsArchitecture();

        try
        {
            // blocking Aysnc get Future call for result
            System.out.println(future.get());
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}

Test.jar имеет значение ниже 2 файл класса

Test. java

final public class TestApp
{
    public Future<String> getOsArchitecture()
    {
        CompletableFuture<String> completableFuture
                = CompletableFuture.supplyAsync(new CustomSupplier());

        return completableFuture;
    }
}

CustomSupplier. java

public class CustomSupplier implements Supplier<String> {
    public CustomSupplier() {
    }

    public String get() {
        //Time consuming complex Task and finally return "os.arch"
        //...
        //...
        //...
        return System.getProperty("os.arch");
    }
}

Однако, когда мы отключаем Java Security Manager, программа работает правильно.

Любая помощь приветствуется.

1 Ответ

1 голос
/ 27 февраля 2020

По умолчанию ForkJoinPool используются потоки, которые не имеют привилегий.

Одним из решений является создание нового экземпляра ForkJoinPool с фабрикой пользовательских потоков или любой другой реализации Executor с использованием обычных потоков. , Уловка в том, что создание собственного пула потоков требует предоставления соответствующих разрешений администратором безопасности.

Альтернативой является выполнение запроса в качестве привилегированного действия, игнорирующее ограничения вызывающего потока:

public class CustomSupplier implements Supplier<String> {
    public CustomSupplier() {
    }

    public String get() {
        //Time consuming complex Task and finally return "os.arch"
        //...
        //...
        //...
        return AccessController.doPrivileged(
            (PrivilegedAction<String>)() -> System.getProperty("os.arch"));
    }
}

Это игнорирует привилегии вызывающей стороны и выполняет запрос с разрешением кода, вызывающего doPrivileged, т.е. ваш CustomSupplier. По умолчанию коду приложения предоставляется право на чтение системного свойства "os.arch".

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

public class CustomSupplier implements Supplier<String> {
    public CustomSupplier() {
    }

    public String get() {
        //Time consuming complex Task and finally return "os.arch"
        //...
        //...
        //...
        return ARCH;
    }
    static final String ARCH = System.getProperty("os.arch");
}
...