java 8个jnlp异步调用和权限

java 8 jnlp asynchronous calls and permissions

我有一个简单的 jnlp 应用程序,它演示了 java 8 个异步调用和访问权限数据,例如 System.getProperties()。我已在 jnlp 文件中授予它完全权限,并且代码已使用适当的 CA 根证书正确签名,但代码仍然抛出异常。我找不到任何可以解释或解决这个问题的东西,据我所知,所有需要的权限都已被授予。有人可以帮忙吗?

代码:

package com.text;
import java.util.Properties;
import java.util.concurrent.*;

public class LambaTest {
    public static void main(String args[]) {
        CompletableFuture<String> test = CompletableFuture.supplyAsync( () -> {
        try {
                System.out.println("Asynchronous Thread");
                Properties properties = System.getProperties();
                System.out.println("https.protocols="+properties.get("https.protocols"));
                System.out.println("Asynchronous Thread successful");
                return "Hello";
            } catch(Exception e) {
                System.out.println("Asynchronous Thread FAILED");
                e.printStackTrace();
            }
            return null;
        });

        test.thenAccept(string -> {
            System.out.println("Priting String within async call " + string);
        });

        try{
            System.out.println("Main Thread");
            Properties properties = System.getProperties();
            System.out.println("https.protocols="+properties.get("https.protocols"));
            System.out.println("Main Thread successful");
        } catch (Exception er) {
            System.out.println("Main Thread FAILED");
            er.printStackTrace();
        }
    }
}

这是 jnlp 描述符:

<?xml version="1.0" encoding="UTF-8"?>
<jnlp spec="1.0+"
  codebase="http://localhost/"
  href="test_uat.jnlp"
>
<information>
  <title>TEST - uat</title>
  <vendor>TESTing service</vendor>
  <homepage href="http://localhost/" />
  <description>JNLP Test scripts</description>
  <offline-allowed/>
</information>
<security>
  <all-permissions/>
</security>
<resources>
  <j2se version="1.8+" />
  <jar href="Test-1.0-SNAPSHOT.jar" download="eager" main="true"/>
</resources>
<application-desc main-class="com.test.LambaTest">
    <argument>empty</argument>
</application-desc>
</jnlp>

这是控制台输出:

Asynchronous Thread
Asynchronous Thread FAILED
java.security.AccessControlException: access denied ("java.util.PropertyPermission" "*" "read,write")
    at java.security.AccessControlContext.checkPermission(Unknown Source)
    at java.security.AccessController.checkPermission(Unknown Source)
    at java.lang.SecurityManager.checkPermission(Unknown Source)
    at com.sun.javaws.security.JavaWebStartSecurity.checkPermission(Unknown Source)
    at java.lang.SecurityManager.checkPropertiesAccess(Unknown Source)
    at java.lang.System.getProperties(Unknown Source)
    at com.test.LambaTest.lambda$main[=13=](LambaTest.java:17)
    at java.util.concurrent.CompletableFuture$AsyncSupply.run(Unknown Source)
    at java.util.concurrent.CompletableFuture$AsyncSupply.exec(Unknown Source)
    at java.util.concurrent.ForkJoinTask.doExec(Unknown Source)
    at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(Unknown Source)
    at java.util.concurrent.ForkJoinPool.runWorker(Unknown Source)
    at java.util.concurrent.ForkJoinWorkerThread.run(Unknown Source)
Priting String within async call null
Main Thread
https.protocols=TLSv1.2,TLSv1.1,TLSv1
Main Thread successful

对于普通的执行,一个方法的权限是当前调用栈上所有方法的权限的交集。

因此,如果调用您的代码的线程池比您的代码具有更少的权限,甚至根本没有权限,那么您的代码在该调用上下文中具有更少甚至没有权限。

这确保了非特权方法不能通过调用不知情的特权方法来简单地执行特权操作。特权方法负责验证调用者的参数,如果操作被认为与安全相关,则执行自己的安全检查,然后显式调用 AccessController.doPrivileged(…) 以声明不应考虑间接调用者的特权。如果没有发生这种情况,非特权调用者仍然不能滥用该方法来提升其权限。

public class LambdaTest {
    public static void main(String args[]) {
        CompletableFuture<String> test = CompletableFuture.supplyAsync(() -> {
            System.out.println("Asynchronous Thread");
            PrivilegedAction<Properties> action = System::getProperties;
            Properties properties = AccessController.doPrivileged(action);
            System.out.println("https.protocols="+properties.get("https.protocols"));
            return "hello";
        }).whenComplete((string, throwable) -> {
            if(throwable != null) {
                System.err.println("async action failed");
                throwable.printStackTrace();
            }
            else System.out.println("Async call returned " + string);
        });

        try{
            System.out.println("Main Thread");
            Properties properties = System.getProperties();
            System.out.println("https.protocols="+properties.get("https.protocols"));
            System.out.println("Main Thread successful");
        } catch (Exception er) {
            System.out.println("Main Thread FAILED");
            er.printStackTrace();
        }
        test.join();
    }
}

顺便说一句,当你想获得一个属性时,你应该使用System.getProperty(String)。正如 System.getProperties() 所述:

Note that even if the security manager does not permit the getProperties operation, it may choose to permit the getProperty(String) operation.