加載別人代碼到沙箱環境運行

沙箱運行代碼

現在有一個需求是:我們需要把別人的代碼加載到我們代碼裏面來運行

如何把別人代碼拿過來呢?

  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;

我畫的一個沙箱模型

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章