簡體   English   中英

安全地重新使用沙盒Nashorn容器

[英]Safely re-using sandboxed Nashorn containers

我正在實現一個沙盒JS環境,該環境允許用戶上傳其JS代碼並根據一組規則觸發它。

我禁止從Nashorn環境訪問Java,只允許訪問一些實用程序類進行一些操作,例如HTTP請求,base64編碼等。

當前,我為用戶上傳的每個JS代碼創建ScriptEngine (Nashorn環境),但是在我們的環境中,我們有很多預定義的JS代碼,大多數用戶都在使用。 由於創建ScriptEngine的成本很高,因此我想對相同的JS代碼塊重復使用ScriptEngine 假設用戶上傳了以下代碼:

var main = function(event, userContext) {
   return event.get('time') + userContext.api_key;
}

userContext工作方式類似於環境變量,用戶在上載代碼時設置上下文變量,然后將其傳遞給main函數。 由於JS代碼除了main之外沒有任何其他變量,因此它是無狀態的,因此重新使用容器很容易。 但是,對於以下代碼塊,重用容器並非易事:

var test = [];
var main = function(event, userContext) {
   test.push(1);
   return event.get('time') + userContext.api_key;
}

我正在尋找一種為每個用戶抽象局部變量,並在不同的局部上下文中重復使用環境的方法,以便Java將JS代碼編譯為Java字節碼,然后一次將其重新使用相同的字節碼,然后在不同的上下文,就像類和對象之間的關系一樣。

一種方法是為每個用戶創建一個ENGINE_SCOPE並在調用main函數時更改綁定。 但是我找不到克隆ScriptObjectMirror 我的計划是在用戶上載預編譯的JS代碼時創建新的作用域,並在調用該函數時使用它。 但是,Nashorn似乎不允許以編程方式創建引擎范圍。

另一個問題是JS允許修改全局對象。 用戶可以毫無問題地執行以下代碼塊,並且對於所有執行, Object將為null

var test = [];
var main = function(event, userContext) {
   Object = null;
   return event.get('time') + userContext.api_key;
}

因此,我還需要禁用對GLOBAL_SCOPE的變量的修改,但是我找不到解決方法。

我知道重復使用容器可能還會遇到其他安全問題,安全的方法是為用戶上傳的每個JS代碼創建不同的容器。 但是,與V8相比,創建Nashorn環境非常昂貴,並且如果運行時Nashorn環境太多,則Java會填充Code Cache因為它會嘗試將JS代碼塊編譯為Java字節碼。 我也樂於接受其他建議來解決此問題。

我相信ScriptContext對象將隔離每個執行。

ScriptEngine engine = new ScriptEngineManager()
        .getEngineByName("nashorn");

// Set up an isolated context.
Bindings bindings = engine.createBindings();
ScriptContext isolatedContext = new SimpleScriptContext();
isolatedContext.setBindings(bindings, ScriptContext.ENGINE_SCOPE);

// Compile the function in the context.
engine.eval(code, isolatedContext);
ScriptObjectMirror fn = (ScriptObjectMirror) isolatedContext
        .getAttribute("main");

// Call it whenever
fn.call("main", arg1, ar2, argEtc);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM