加载别人代码到沙箱环境运行

沙箱运行代码

现在有一个需求是:我们需要把别人的代码加载到我们代码里面来运行

如何把别人代码拿过来呢?

  1. 可以利用git把代码下载下来
  2. 利用maven进行打包编译(.java编译成.class文件)
  3. 加载.class文件形成object对象
  4. 运行我们想要的函数
Git git = Git.cloneRepository().setURI(gitUrl).setDirectory(localRepoFile).call();
InvocationRequest request = new DefaultInvocationRequest();
request.setPomFile(new File(localRepoPath + "/pom.xml"));
request.setGoals(Collections.singletonList("package"));
request.setMavenOpts("-Dmaven.test.skip=true");
Invoker invoker = new DefaultInvoker();
invoker.setMavenHome(new File(自己的maven目录));
invoker.execute(request);

如何安全的运行别人代码呢?

  1. 利用java的沙箱机制

java沙箱介绍

java安全沙箱的前三类保证了jvm所运行程序的完整性,使得jvm不会因为运行有漏洞或恶意的代码而导致出现不可预期的状态。而第四类沙箱模型是“类安全管理器及Java API”,它能保护jvm在运行有漏洞或恶意的代码不会破坏外部资源。java通过称为安全管理器的一类API来保证这类安全性。

启动沙箱的方法

  1. 在java进程启动的时候,以命令的方式直接指定沙箱运行环境,具体的权限可以在安全策略文件中配置
  2. 用代码的形式在程序中启动
安全策略文件在 $JAVA_HOME/jre/lib/security/java.policy来指定访问外部资源的权限,该策略文件也可以通过jvm参数-Djava.security.policy来指定。
Policy文件的主要格式如下:
keystore "some_keystore_url", "keystore_type";
grant [SignedBy "signer_names"] [, CodeBase "URL"] {
    Permission permission_class_name ["target_name"] [,"action"] [,SignedBy"signer_names"];
    … …
};
"keystore":一个keystore是一个私有密钥(private keys)数据库和相应的数字签名
"grant":在Policy文件中的每一个grant记录含有一个CodeSource(指定代码)及其permission(许可)
// 启用安全管理器
System.setSecurityManager(new SecurityManager());

问题

上面两种办法都有一个缺陷:一旦启动之后就完全是沙箱了,但这并不符合我们的要求,沙箱只是运行用户的那段代码,之后还有很多代码是和用户代码无关的,比如和主进程进行RPC通信,加载.class等操作。

解决问题

  1. 多进程(为每个用户起一个进程,并指定java程序运行的内存最大限制)
  2. 利用代理模式(System.setSecurityManager(自己实现一个SecurityManager);)
java -jar -Xms1024m -Xmx1024m XX.jar
Xms:表示jvm所需最小内存
Xmx:表示jvm所需最大内存
自己实现一个MySecurityManager继承SecurityManager,里面每次进行权限检查的时候都会调用checkPermission方法,我们重写这个方法,并在外面new一个SecurityManager,让他在跑别人代码的时候调用这个SecurityManager的checkPermission方法,跑我们的代码的时候直接返回return;

我画的一个沙箱模型

加载别人代码到沙箱环境运行_第1张图片

你可能感兴趣的:(JAVA,沙箱,maven打包编译)