[英]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.