java - 启用 java 安全管理器时,获取系统属性 "os.arch"时权限被拒绝

标签 java java.util.concurrent completable-future java-security java-security-manager

我有一个简单的java应用程序ClientApp,它启用了Java安全管理器。 此应用程序正在尝试调用测试 jar 的方法,该方法获取“os.arch”系统属性。由于这很耗时,我们使用 Completable 任务调用一个新线程。

这给出了异常(exception)

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)

客户端应用程序:

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 个类文件

测试.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安全管理器时,程序可以正常运行。

非常感谢任何帮助。

最佳答案

默认的ForkJoinPool使用配置为没有权限的线程。

一种解决方案是使用自定义线程工厂或使用普通线程的任何其他 Executor 实现创建新的 ForkJoinPool 实例。问题是创建自己的线程池需要安全管理器授予相关权限。

另一种方法是将查询作为特权操作执行,忽略调用线程的限制:

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");
}

关于java - 启用 java 安全管理器时,获取系统属性 "os.arch"时权限被拒绝,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60373662/

相关文章:

java - 如何使用 IntelliJ IDEA 而不是通过 shell 构建 Java 项目?

java - 具有相同路径的 JAX-RS 多个类

java - CompletableFuture 如何知道任务是独立的?

java - CompletableFuture allof(..).join() 与 CompletableFuture.join()

kotlin - Kotlin 中的并发 Future 语法

java - Mongodb 对象是否绑定(bind)到单个 Mongod 实例?

java - 集合中的键递增

java - ConcurrentHashMap中的并发修改

java.util.concurrent.ScheduledExecutorService 运行频率很低

java - 我应该在每个服务方法上放置 @Async 以使我的应用程序完全支持 Spring 中的异步吗?