2016-11-27 57 views
0

我正在實現一個沙盒JS環境,它允許用戶上傳他們的JS代碼並根據一組規則觸發它。安全地重新使用沙盒容器

我從犀牛環境中禁用Java訪問,只允許訪問某些工具類,如HTTP請求,base64編碼等

目前,我創建ScriptEngine(犀牛環境)由上載的每個JS代碼的幾個操作用戶,但在我們的環境中,我們有許多預定義的JS代碼,這些代碼被大多數用戶使用。由於創建ScriptEngine是昂貴的,我想要爲相同的JS代碼塊重新使用ScriptEngine。比方說,用戶上傳下面的代碼:

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允許修改全局對象。用戶可以在沒有任何問題,執行下面的代碼塊和Objectnull對所有執行:

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字節碼。我也接受其他建議來解決這個問題。

回答

0

我相信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); 
+0

我沒有得到什麼ScriptObjectMirror。但我會嘗試你的方法,並讓你知道謝謝 – Zo72

+0

它不起作用。如果我的代碼是「new java.util.HashMap()」,它允許我創建它......這完全挫敗了我的目的 – Zo72